Initial commit: OCA Technical packages (595 packages)

This commit is contained in:
Ernad Husremovic 2025-08-29 15:43:03 +02:00
commit 2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions

View file

@ -0,0 +1,45 @@
# Leaflet Map View (OpenStreetMap)
Odoo addon: web_view_leaflet_map
## Installation
```bash
pip install odoo-bringout-oca-geospatial-web_view_leaflet_map
```
## Dependencies
This addon depends on:
- base_geolocalize
- web_leaflet_lib
## Manifest Information
- **Name**: Leaflet Map View (OpenStreetMap)
- **Version**: 16.0.2.0.0
- **Category**: Extra Tools
- **License**: AGPL-3
- **Installable**: True
## Source
Based on [OCA/geospatial](https://github.com/OCA/geospatial) branch 16.0, addon `web_view_leaflet_map`.
## License
This package maintains the original AGPL-3 license from the upstream Odoo project.
## Documentation
- Overview: doc/OVERVIEW.md
- Architecture: doc/ARCHITECTURE.md
- Models: doc/MODELS.md
- Controllers: doc/CONTROLLERS.md
- Wizards: doc/WIZARDS.md
- Install: doc/INSTALL.md
- Usage: doc/USAGE.md
- Configuration: doc/CONFIGURATION.md
- Dependencies: doc/DEPENDENCIES.md
- Troubleshooting: doc/TROUBLESHOOTING.md
- FAQ: doc/FAQ.md

View file

@ -0,0 +1,32 @@
# Architecture
```mermaid
flowchart TD
U[Users] -->|HTTP| V[Views and QWeb Templates]
V --> C[Controllers]
V --> W[Wizards Transient Models]
C --> M[Models and ORM]
W --> M
M --> R[Reports]
DX[Data XML] --> M
S[Security ACLs and Groups] -. enforces .-> M
subgraph Web_view_leaflet_map Module - web_view_leaflet_map
direction LR
M:::layer
W:::layer
C:::layer
V:::layer
R:::layer
S:::layer
DX:::layer
end
classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px
```
Notes
- Views include tree/form/kanban templates and report templates.
- Controllers provide website/portal routes when present.
- Wizards are UI flows implemented with `models.TransientModel`.
- Data XML loads data/demo records; Security defines groups and access.

View file

@ -0,0 +1,3 @@
# Configuration
Refer to Odoo settings for web_view_leaflet_map. Configure related models, access rights, and options as needed.

View file

@ -0,0 +1,3 @@
# Controllers
This module does not define custom HTTP controllers.

View file

@ -0,0 +1,6 @@
# Dependencies
This addon depends on:
- [base_geolocalize](../../odoo-bringout-oca-ocb-base_geolocalize)
- [web_leaflet_lib](../../odoo-bringout-oca-geospatial-web_leaflet_lib)

View file

@ -0,0 +1,4 @@
# FAQ
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
- Q: How to enable? A: Start server with --addon web_view_leaflet_map or install in UI.

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-geospatial-web_view_leaflet_map"
# or
uv pip install odoo-bringout-oca-geospatial-web_view_leaflet_map"
```

View file

@ -0,0 +1,14 @@
# Models
Detected core models and extensions in web_view_leaflet_map.
```mermaid
classDiagram
class ir_actions_act_window_view
class ir_ui_view
class res_users
```
Notes
- Classes show model technical names; fields omitted for brevity.
- Items listed under _inherit are extensions of existing models.

View file

@ -0,0 +1,6 @@
# Overview
Packaged Odoo addon: web_view_leaflet_map. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon web_view_leaflet_map
- License: LGPL-3

View file

@ -0,0 +1,3 @@
# Reports
This module does not define custom reports.

View file

@ -0,0 +1,8 @@
# Security
This module does not define custom security rules or access controls beyond Odoo defaults.
Default Odoo security applies:
- Base user access through standard groups
- Model access inherited from dependencies
- No custom row-level security rules

View file

@ -0,0 +1,5 @@
# Troubleshooting
- Ensure Python and Odoo environment matches repo guidance.
- Check database connectivity and logs if startup fails.
- Validate that dependent addons listed in DEPENDENCIES.md are installed.

View file

@ -0,0 +1,7 @@
# Usage
Start Odoo including this addon (from repo root):
```bash
python3 scripts/nix_odoo_web_server.py --db-name mydb --addon web_view_leaflet_map
```

View file

@ -0,0 +1,3 @@
# Wizards
This module does not include UI wizards.

View file

@ -0,0 +1,43 @@
[project]
name = "odoo-bringout-oca-geospatial-web_view_leaflet_map"
version = "16.0.0"
description = "Leaflet Map View (OpenStreetMap) - Add new 'leaflet_map' view, to display markers."
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-geospatial-base_geolocalize>=16.0.0",
"odoo-bringout-oca-geospatial-web_leaflet_lib>=16.0.0",
"requests>=2.25.1"
]
readme = "README.md"
requires-python = ">= 3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Office/Business",
]
[project.urls]
homepage = "https://github.com/bringout/0"
repository = "https://github.com/bringout/0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["web_view_leaflet_map"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]

View file

@ -0,0 +1,182 @@
================================
Leaflet Map View (OpenStreetMap)
================================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f494ec35cbd29ae4bcc5e46a7a30bf5b2261bd449a3b0ba08a95a70d45dbea12
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png
:target: https://odoo-community.org/page/development-status
:alt: Alpha
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fgeospatial-lightgray.png?logo=github
:target: https://github.com/OCA/geospatial/tree/16.0/web_view_leaflet_map
:alt: OCA/geospatial
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/geospatial-16-0/geospatial-16-0-web_view_leaflet_map
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/geospatial&target_branch=16.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module extends odoo views, to add a new kind of view, named ``leaflet_map``
that is using the Leaflet javascript library to use maps. (https://leafletjs.com/)
This library is for exemple, used in the OpenStreetMap project. (https://www.openstreetmap.org/)
You can see a simple usage in the module ``web_view_leaflet_map_partner`` in the
same OCA repository that displays your contact in a map, if latitude and longitude are
defined. (To define latitude and longitude, refer to the Odoo module ``base_geolocalize``)
.. figure:: https://raw.githubusercontent.com/OCA/geospatial/16.0/web_view_leaflet_map/static/description/view_res_partner_map_1.png
.. figure:: https://raw.githubusercontent.com/OCA/geospatial/16.0/web_view_leaflet_map/static/description/view_res_partner_map_2.png
.. IMPORTANT::
This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.
`More details on development status <https://odoo-community.org/page/development-status>`_
**Table of contents**
.. contents::
:local:
Configuration
=============
* See configuration of the module ``web_leaflet_lib``.
Development
===========
Create a new view :
.. code-block:: xml
<record id="view_my_model_map" model="ir.ui.view">
<field name="model">my.model</field>
<field name="arch" type="xml">
<leaflet_map
field_latitude="FIELD_LATITUDE"
field_longitude="FIELD_LONGITUDE"
field_title="FIELD_TITLE"
field_address="FIELD_ADDRESS"
field_marker_icon_image="FIELD_MARKER_ICON_IMAGE"
>
<field name="__last_update"/>
<field name="FIELD_LATITUDE"/>
<field name="FIELD_LONGITUDE"/>
<field name="FIELD_TITLE"/>
<field name="FIELD_ADDRESS"/>
</leaflet_map>
</field>
</record>
1. FIELD_LATITUDE and FIELD_LONGITUDE are the name of the fields that contains GPS coordinates of the model.
2. FIELD_TITLE will be used when the popup is displayed, as a title.
3. FIELD_ADDRESS will be used when the popup is displayed to display the adress.
4. (optional) FIELD_MARKER_ICON_IMAGE, is the name of the image field to place as an icon
of the marker.
Note: You can set extra settings ``marker_icon_size_x``, ``marker_icon_size_y``, to define
the size of the image, and ``marker_popup_anchor_x``, ``marker_popup_anchor_y`` to define
the position of the popup.
Map options :
- ``default_zoom`` : define the default zoom value. (7 if not defined)
- ``max_zoom`` : define the max zoom value. (19 if not defined)
- ``zoom_snap`` : define the zoom level in each change. (1 if not defined)
* Create or update an action for the model
.. code-block:: xml
<record id="my_module.action_my_model" model="ir.actions.act_window">
<field name="view_mode">tree,form,leaflet_map</field>
</record>
**Library Update**
For the time being, the module embed the lealflet.js library version 1.8.0 ( released on April 18, 2022.)
If a new release is out:
- please download it here https://leafletjs.com/download.html
- update the javascript, css and images, present in the folder ``static/lib/leaflet``
- test the features
- make a Pull Request
**Default position in the map**
By default, the position of the map is defined by the user, in the function
``get_default_leaflet_position``. It returns the position of the current company, if defined.
you can overload this function globally, or per model.
Known issues / Roadmap
======================
* For the time being, at the start of the map loading, the call of ``invalidateSize()``
is required. We should investigate why and try to remove that call.
see https://github.com/Leaflet/Leaflet/issues/3002#issuecomment-93836022
* For the time being, the map has "Markers" and allow to display odoo items
if longitude and latitude are available. We could imagine other kind of usages,
with Polylines, Polygons, etc...
See all the leaflet options : https://leafletjs.com/reference.html
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/geospatial/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/geospatial/issues/new?body=module:%20web_view_leaflet_map%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* GRAP
Contributors
~~~~~~~~~~~~
* Sylvain LE GAL (https://www.twitter.com/legalsylvain)
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
.. |maintainer-legalsylvain| image:: https://github.com/legalsylvain.png?size=40px
:target: https://github.com/legalsylvain
:alt: legalsylvain
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|maintainer-legalsylvain|
This module is part of the `OCA/geospatial <https://github.com/OCA/geospatial/tree/16.0/web_view_leaflet_map>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View file

@ -0,0 +1,2 @@
from . import models
from .hooks import uninstall_hook

View file

@ -0,0 +1,29 @@
# Copyright (C) 2022 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Leaflet Map View (OpenStreetMap)",
"summary": "Add new 'leaflet_map' view, to display markers.",
"version": "16.0.2.0.0",
"development_status": "Alpha",
"author": "GRAP, Odoo Community Association (OCA)",
"maintainers": ["legalsylvain"],
"website": "https://github.com/OCA/geospatial",
"license": "AGPL-3",
"category": "Extra Tools",
"depends": [
"base_geolocalize",
"web_leaflet_lib",
],
"assets": {
"web.assets_backend": [
"web_view_leaflet_map/static/src/js/view/view_registry.js",
"web_view_leaflet_map/static/src/js/view/map/map_renderer.js",
"web_view_leaflet_map/static/src/js/view/map/map_view.js",
"web_view_leaflet_map/static/src/css/web_view_leaflet_map.css",
],
},
"installable": True,
"uninstall_hook": "uninstall_hook",
}

View file

@ -0,0 +1,18 @@
# Copyright (C) 2019, Open Source Integrators
# Copyright (C) 2022 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
def uninstall_hook(cr, registry):
cr.execute(
"UPDATE ir_act_window "
"SET view_mode=replace(view_mode, ',leaflet_map', '')"
"WHERE view_mode LIKE '%,leaflet_map%';"
)
cr.execute(
"UPDATE ir_act_window "
"SET view_mode=replace(view_mode, 'leaflet_map,', '')"
"WHERE view_mode LIKE '%leaflet_map,%';"
)
cr.execute("DELETE FROM ir_act_window " "WHERE view_mode = 'leaflet_map';")

View file

@ -0,0 +1,49 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_view_leaflet_map
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \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"
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_ir_actions_act_window_view
msgid "Action Window View"
msgstr "— ili —"
#. module: web_view_leaflet_map
#: model:ir.model.fields.selection,name:web_view_leaflet_map.selection__ir_actions_act_window_view__view_mode__leaflet_map
#: model:ir.model.fields.selection,name:web_view_leaflet_map.selection__ir_ui_view__type__leaflet_map
msgid "Leaflet Map"
msgstr "Leaflet mapa"
#. module: web_view_leaflet_map
#. odoo-javascript
#: code:addons/web_view_leaflet_map/static/src/js/view/map/map_view.js:0
#, python-format
msgid "Map"
msgstr "Mapa"
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_res_users
msgid "User"
msgstr "Korisnik"
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_ir_ui_view
msgid "View"
msgstr "Pregled"
#. module: web_view_leaflet_map
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_ir_actions_act_window_view__view_mode
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_ir_ui_view__type
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_website_page__type
msgid "View Type"
msgstr "Vrsta pregleda"

View file

@ -0,0 +1,79 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_view_leaflet_map
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-09-18 19:56+0000\n"
"PO-Revision-Date: 2022-09-18 19:56+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_ir_actions_act_window_view
msgid "Action Window View"
msgstr "Vue de la Fenêtre d'Action"
#. module: web_view_leaflet_map
#: model:ir.model.fields.selection,name:web_view_leaflet_map.selection__ir_actions_act_window_view__view_mode__leaflet_map
#: model:ir.model.fields.selection,name:web_view_leaflet_map.selection__ir_ui_view__type__leaflet_map
msgid "Leaflet Map"
msgstr "Carte Leaflet"
#. module: web_view_leaflet_map
#. odoo-javascript
#: code:addons/web_view_leaflet_map/static/src/js/view/map/map_view.js:0
#, python-format
msgid "Map"
msgstr "Carte"
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_res_users
msgid "User"
msgstr ""
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_ir_ui_view
msgid "View"
msgstr "Vue"
#. module: web_view_leaflet_map
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_ir_actions_act_window_view__view_mode
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_ir_ui_view__type
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_website_page__type
msgid "View Type"
msgstr "Type de Vue"
#~ msgid "Activity"
#~ msgstr "Activité"
#~ msgid "Calendar"
#~ msgstr "Calendrier"
#~ msgid "Diagram"
#~ msgstr "Diagramme"
#~ msgid "Form"
#~ msgstr "Formulaire"
#~ msgid "Graph"
#~ msgstr "Graphique"
#~ msgid "Pivot"
#~ msgstr "Tableau croisé dynamique"
#~ msgid "Search"
#~ msgstr "Rechercher"
#~ msgid "Tree"
#~ msgstr "Arborescence"
#~ msgid "Users"
#~ msgstr "Utilisateurs"

View file

@ -0,0 +1,52 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_view_leaflet_map
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-01-26 08:36+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 4.17\n"
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_ir_actions_act_window_view
msgid "Action Window View"
msgstr "Vista maschera azione"
#. module: web_view_leaflet_map
#: model:ir.model.fields.selection,name:web_view_leaflet_map.selection__ir_actions_act_window_view__view_mode__leaflet_map
#: model:ir.model.fields.selection,name:web_view_leaflet_map.selection__ir_ui_view__type__leaflet_map
msgid "Leaflet Map"
msgstr "Mappa Leaflet"
#. module: web_view_leaflet_map
#. odoo-javascript
#: code:addons/web_view_leaflet_map/static/src/js/view/map/map_view.js:0
#, python-format
msgid "Map"
msgstr "Mappa"
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_res_users
msgid "User"
msgstr "Utente"
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_ir_ui_view
msgid "View"
msgstr "Vista"
#. module: web_view_leaflet_map
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_ir_actions_act_window_view__view_mode
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_ir_ui_view__type
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_website_page__type
msgid "View Type"
msgstr "Tipo vista"

View file

@ -0,0 +1,49 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * web_view_leaflet_map
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \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"
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_ir_actions_act_window_view
msgid "Action Window View"
msgstr ""
#. module: web_view_leaflet_map
#: model:ir.model.fields.selection,name:web_view_leaflet_map.selection__ir_actions_act_window_view__view_mode__leaflet_map
#: model:ir.model.fields.selection,name:web_view_leaflet_map.selection__ir_ui_view__type__leaflet_map
msgid "Leaflet Map"
msgstr ""
#. module: web_view_leaflet_map
#. odoo-javascript
#: code:addons/web_view_leaflet_map/static/src/js/view/map/map_view.js:0
#, python-format
msgid "Map"
msgstr ""
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_res_users
msgid "User"
msgstr ""
#. module: web_view_leaflet_map
#: model:ir.model,name:web_view_leaflet_map.model_ir_ui_view
msgid "View"
msgstr ""
#. module: web_view_leaflet_map
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_ir_actions_act_window_view__view_mode
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_ir_ui_view__type
#: model:ir.model.fields,field_description:web_view_leaflet_map.field_website_page__type
msgid "View Type"
msgstr ""

View file

@ -0,0 +1,3 @@
from . import ir_act_window_view
from . import ir_ui_view
from . import res_users

View file

@ -0,0 +1,15 @@
# Copyright (C) 2019, Open Source Integrators
# Copyright (C) 2022 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class IrActionsActWindowView(models.Model):
_inherit = "ir.actions.act_window.view"
view_mode = fields.Selection(
selection_add=[("leaflet_map", "Leaflet Map")],
ondelete={"leaflet_map": "cascade"},
)

View file

@ -0,0 +1,12 @@
# Copyright (C) 2019, Open Source Integrators
# Copyright (C) 2022 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import fields, models
class IrUiView(models.Model):
_inherit = "ir.ui.view"
type = fields.Selection(selection_add=[("leaflet_map", "Leaflet Map")])

View file

@ -0,0 +1,17 @@
# Copyright (C) 2022 - Today: GRAP (http://www.grap.coop)
# @author: Sylvain LE GAL (https://twitter.com/legalsylvain)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, models
class ResUsers(models.Model):
_inherit = "res.users"
@api.model
def get_default_leaflet_position(self, model_name):
current_partner = self.env.user.company_id.partner_id
return {
"lat": current_partner.partner_latitude,
"lng": current_partner.partner_longitude,
}

View file

@ -0,0 +1 @@
* See configuration of the module ``web_leaflet_lib``.

View file

@ -0,0 +1 @@
* Sylvain LE GAL (https://www.twitter.com/legalsylvain)

View file

@ -0,0 +1,11 @@
This module extends odoo views, to add a new kind of view, named ``leaflet_map``
that is using the Leaflet javascript library to use maps. (https://leafletjs.com/)
This library is for exemple, used in the OpenStreetMap project. (https://www.openstreetmap.org/)
You can see a simple usage in the module ``web_view_leaflet_map_partner`` in the
same OCA repository that displays your contact in a map, if latitude and longitude are
defined. (To define latitude and longitude, refer to the Odoo module ``base_geolocalize``)
.. figure:: ../static/description/view_res_partner_map_1.png
.. figure:: ../static/description/view_res_partner_map_2.png

View file

@ -0,0 +1,62 @@
Create a new view :
.. code-block:: xml
<record id="view_my_model_map" model="ir.ui.view">
<field name="model">my.model</field>
<field name="arch" type="xml">
<leaflet_map
field_latitude="FIELD_LATITUDE"
field_longitude="FIELD_LONGITUDE"
field_title="FIELD_TITLE"
field_address="FIELD_ADDRESS"
field_marker_icon_image="FIELD_MARKER_ICON_IMAGE"
>
<field name="__last_update"/>
<field name="FIELD_LATITUDE"/>
<field name="FIELD_LONGITUDE"/>
<field name="FIELD_TITLE"/>
<field name="FIELD_ADDRESS"/>
</leaflet_map>
</field>
</record>
1. FIELD_LATITUDE and FIELD_LONGITUDE are the name of the fields that contains GPS coordinates of the model.
2. FIELD_TITLE will be used when the popup is displayed, as a title.
3. FIELD_ADDRESS will be used when the popup is displayed to display the adress.
4. (optional) FIELD_MARKER_ICON_IMAGE, is the name of the image field to place as an icon
of the marker.
Note: You can set extra settings ``marker_icon_size_x``, ``marker_icon_size_y``, to define
the size of the image, and ``marker_popup_anchor_x``, ``marker_popup_anchor_y`` to define
the position of the popup.
Map options :
- ``default_zoom`` : define the default zoom value. (7 if not defined)
- ``max_zoom`` : define the max zoom value. (19 if not defined)
- ``zoom_snap`` : define the zoom level in each change. (1 if not defined)
* Create or update an action for the model
.. code-block:: xml
<record id="my_module.action_my_model" model="ir.actions.act_window">
<field name="view_mode">tree,form,leaflet_map</field>
</record>
**Library Update**
For the time being, the module embed the lealflet.js library version 1.8.0 ( released on April 18, 2022.)
If a new release is out:
- please download it here https://leafletjs.com/download.html
- update the javascript, css and images, present in the folder ``static/lib/leaflet``
- test the features
- make a Pull Request
**Default position in the map**
By default, the position of the map is defined by the user, in the function
``get_default_leaflet_position``. It returns the position of the current company, if defined.
you can overload this function globally, or per model.

View file

@ -0,0 +1,8 @@
* For the time being, at the start of the map loading, the call of ``invalidateSize()``
is required. We should investigate why and try to remove that call.
see https://github.com/Leaflet/Leaflet/issues/3002#issuecomment-93836022
* For the time being, the map has "Markers" and allow to display odoo items
if longitude and latitude are available. We could imagine other kind of usages,
with Polylines, Polygons, etc...
See all the leaflet options : https://leafletjs.com/reference.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View file

@ -0,0 +1,524 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Leaflet Map View (OpenStreetMap)</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="leaflet-map-view-openstreetmap">
<h1 class="title">Leaflet Map View (OpenStreetMap)</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:f494ec35cbd29ae4bcc5e46a7a30bf5b2261bd449a3b0ba08a95a70d45dbea12
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Alpha" src="https://img.shields.io/badge/maturity-Alpha-red.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/geospatial/tree/16.0/web_view_leaflet_map"><img alt="OCA/geospatial" src="https://img.shields.io/badge/github-OCA%2Fgeospatial-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/geospatial-16-0/geospatial-16-0-web_view_leaflet_map"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/geospatial&amp;target_branch=16.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module extends odoo views, to add a new kind of view, named <tt class="docutils literal">leaflet_map</tt>
that is using the Leaflet javascript library to use maps. (<a class="reference external" href="https://leafletjs.com/">https://leafletjs.com/</a>)
This library is for exemple, used in the OpenStreetMap project. (<a class="reference external" href="https://www.openstreetmap.org/">https://www.openstreetmap.org/</a>)</p>
<p>You can see a simple usage in the module <tt class="docutils literal">web_view_leaflet_map_partner</tt> in the
same OCA repository that displays your contact in a map, if latitude and longitude are
defined. (To define latitude and longitude, refer to the Odoo module <tt class="docutils literal">base_geolocalize</tt>)</p>
<div class="figure">
<img alt="https://raw.githubusercontent.com/OCA/geospatial/16.0/web_view_leaflet_map/static/description/view_res_partner_map_1.png" src="https://raw.githubusercontent.com/OCA/geospatial/16.0/web_view_leaflet_map/static/description/view_res_partner_map_1.png" />
</div>
<div class="figure">
<img alt="https://raw.githubusercontent.com/OCA/geospatial/16.0/web_view_leaflet_map/static/description/view_res_partner_map_2.png" src="https://raw.githubusercontent.com/OCA/geospatial/16.0/web_view_leaflet_map/static/description/view_res_partner_map_2.png" />
</div>
<div class="admonition important">
<p class="first admonition-title">Important</p>
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
Only for development or testing purpose, do not use in production.
<a class="reference external" href="https://odoo-community.org/page/development-status">More details on development status</a></p>
</div>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#development" id="toc-entry-2">Development</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-3">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-4">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-5">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-6">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-7">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-8">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<ul class="simple">
<li>See configuration of the module <tt class="docutils literal">web_leaflet_lib</tt>.</li>
</ul>
</div>
<div class="section" id="development">
<h1><a class="toc-backref" href="#toc-entry-2">Development</a></h1>
<p>Create a new view :</p>
<pre class="code xml literal-block">
<span class="nt">&lt;record</span><span class="w"> </span><span class="na">id=</span><span class="s">&quot;view_my_model_map&quot;</span><span class="w"> </span><span class="na">model=</span><span class="s">&quot;ir.ui.view&quot;</span><span class="nt">&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;model&quot;</span><span class="nt">&gt;</span>my.model<span class="nt">&lt;/field&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;arch&quot;</span><span class="w"> </span><span class="na">type=</span><span class="s">&quot;xml&quot;</span><span class="nt">&gt;</span><span class="w">
</span><span class="nt">&lt;leaflet_map</span><span class="w">
</span><span class="na">field_latitude=</span><span class="s">&quot;FIELD_LATITUDE&quot;</span><span class="w">
</span><span class="na">field_longitude=</span><span class="s">&quot;FIELD_LONGITUDE&quot;</span><span class="w">
</span><span class="na">field_title=</span><span class="s">&quot;FIELD_TITLE&quot;</span><span class="w">
</span><span class="na">field_address=</span><span class="s">&quot;FIELD_ADDRESS&quot;</span><span class="w">
</span><span class="na">field_marker_icon_image=</span><span class="s">&quot;FIELD_MARKER_ICON_IMAGE&quot;</span><span class="w">
</span><span class="nt">&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;__last_update&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;FIELD_LATITUDE&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;FIELD_LONGITUDE&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;FIELD_TITLE&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;FIELD_ADDRESS&quot;</span><span class="nt">/&gt;</span><span class="w">
</span><span class="nt">&lt;/leaflet_map&gt;</span><span class="w">
</span><span class="nt">&lt;/field&gt;</span><span class="w">
</span><span class="nt">&lt;/record&gt;</span>
</pre>
<ol class="arabic simple">
<li>FIELD_LATITUDE and FIELD_LONGITUDE are the name of the fields that contains GPS coordinates of the model.</li>
<li>FIELD_TITLE will be used when the popup is displayed, as a title.</li>
<li>FIELD_ADDRESS will be used when the popup is displayed to display the adress.</li>
<li>(optional) FIELD_MARKER_ICON_IMAGE, is the name of the image field to place as an icon
of the marker.
Note: You can set extra settings <tt class="docutils literal">marker_icon_size_x</tt>, <tt class="docutils literal">marker_icon_size_y</tt>, to define
the size of the image, and <tt class="docutils literal">marker_popup_anchor_x</tt>, <tt class="docutils literal">marker_popup_anchor_y</tt> to define
the position of the popup.</li>
</ol>
<p>Map options :</p>
<ul class="simple">
<li><tt class="docutils literal">default_zoom</tt> : define the default zoom value. (7 if not defined)</li>
<li><tt class="docutils literal">max_zoom</tt> : define the max zoom value. (19 if not defined)</li>
<li><tt class="docutils literal">zoom_snap</tt> : define the zoom level in each change. (1 if not defined)</li>
</ul>
<ul class="simple">
<li>Create or update an action for the model</li>
</ul>
<pre class="code xml literal-block">
<span class="nt">&lt;record</span><span class="w"> </span><span class="na">id=</span><span class="s">&quot;my_module.action_my_model&quot;</span><span class="w"> </span><span class="na">model=</span><span class="s">&quot;ir.actions.act_window&quot;</span><span class="nt">&gt;</span><span class="w">
</span><span class="nt">&lt;field</span><span class="w"> </span><span class="na">name=</span><span class="s">&quot;view_mode&quot;</span><span class="nt">&gt;</span>tree,form,leaflet_map<span class="nt">&lt;/field&gt;</span><span class="w">
</span><span class="nt">&lt;/record&gt;</span>
</pre>
<p><strong>Library Update</strong></p>
<p>For the time being, the module embed the lealflet.js library version 1.8.0 ( released on April 18, 2022.)</p>
<p>If a new release is out:</p>
<ul class="simple">
<li>please download it here <a class="reference external" href="https://leafletjs.com/download.html">https://leafletjs.com/download.html</a></li>
<li>update the javascript, css and images, present in the folder <tt class="docutils literal">static/lib/leaflet</tt></li>
<li>test the features</li>
<li>make a Pull Request</li>
</ul>
<p><strong>Default position in the map</strong></p>
<p>By default, the position of the map is defined by the user, in the function
<tt class="docutils literal">get_default_leaflet_position</tt>. It returns the position of the current company, if defined.
you can overload this function globally, or per model.</p>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-3">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>For the time being, at the start of the map loading, the call of <tt class="docutils literal">invalidateSize()</tt>
is required. We should investigate why and try to remove that call.
see <a class="reference external" href="https://github.com/Leaflet/Leaflet/issues/3002#issuecomment-93836022">https://github.com/Leaflet/Leaflet/issues/3002#issuecomment-93836022</a></li>
<li>For the time being, the map has “Markers” and allow to display odoo items
if longitude and latitude are available. We could imagine other kind of usages,
with Polylines, Polygons, etc…
See all the leaflet options : <a class="reference external" href="https://leafletjs.com/reference.html">https://leafletjs.com/reference.html</a></li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-4">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/geospatial/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/geospatial/issues/new?body=module:%20web_view_leaflet_map%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-5">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-6">Authors</a></h2>
<ul class="simple">
<li>GRAP</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-7">Contributors</a></h2>
<ul class="simple">
<li>Sylvain LE GAL (<a class="reference external" href="https://www.twitter.com/legalsylvain">https://www.twitter.com/legalsylvain</a>)</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
<p><a class="reference external image-reference" href="https://github.com/legalsylvain"><img alt="legalsylvain" src="https://github.com/legalsylvain.png?size=40px" /></a></p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/geospatial/tree/16.0/web_view_leaflet_map">OCA/geospatial</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

View file

@ -0,0 +1,60 @@
/*
Custom CSS for the elements introduced by web_view_leaflet_map module
*/
.o_leaflet_main_container {
display: flex;
align-content: stretch;
overflow-x: visible;
height: 100%;
width: 100%;
}
.o_leaflet_map_container {
height: 100%;
width: 100%;
}
.o_map_selector {
cursor: pointer;
}
.o_map_selector:hover {
background-color: #eee;
}
.leaflet_marker_icon {
background-color: white;
border: 1px black solid;
border-radius: 50% !important;
}
/*
Overload leaflet CSS to work with custom specific things of Odoo CSS
*/
/* hide close button to avoid bad navigation experience
Before that patch, if user click on the 'close' button, the home page will be loaded.
(popup can be hidden by clicking out of the popup, on the map)
*/
.leaflet-popup-close-button {
display: none;
}
/* Change z-index from 1000 to 999 to avoid to conflict with odoo menu that are set to 1000
See : https://github.com/odoo/odoo/blob/12.0/addons/web/static/lib/bootstrap/css/bootstrap.css#L2991
*/
.leaflet-top,
.leaflet-bottom {
z-index: 999 !important;
}
/* Odoo is hiding (with display directive) all the aria-hidden elements of Odoo
that prevent to display buttons introduced by the leaflet library.
This directive force to display the elements for the leaflet elements.
See : https://github.com/odoo/odoo/blob/12.0/addons/web/static/src/scss/ui.scss#L13
*/
.leaflet-container [aria-hidden="true"],
[aria-hidden="1"] {
display: inline !important;
}

View file

@ -0,0 +1,178 @@
odoo.define("web_view_leaflet_map.MapRenderer", function (require) {
"use strict";
var AbstractRenderer = require("web.AbstractRenderer");
var session = require("web.session");
var field_utils = require("web.field_utils");
var MapRenderer = AbstractRenderer.extend({
tagName: "div",
className: "o_leaflet_main_container",
init: function (parent, state, params) {
this._super.apply(this, arguments);
this.leaflet_tile_url = session["leaflet.tile_url"];
this.leaflet_copyright = session["leaflet.copyright"];
this.default_zoom = params.arch.attrs.default_zoom || 7;
this.max_zoom = params.arch.attrs.max_zoom || 19;
this.zoom_snap = params.arch.attrs.zoom_snap | 1;
this.field_latitude = params.arch.attrs.field_latitude;
this.field_longitude = params.arch.attrs.field_longitude;
this.field_title = params.arch.attrs.field_title;
this.field_address = params.arch.attrs.field_address;
this.field_marker_icon_image = params.arch.attrs.field_marker_icon_image;
this.marker_icon_size_x = params.arch.attrs.marker_icon_size_x || 64;
this.marker_icon_size_y = params.arch.attrs.marker_icon_size_y || 64;
this.marker_popup_anchor_x = params.arch.attrs.marker_popup_anchor_x || 0;
this.marker_popup_anchor_y = params.arch.attrs.marker_popup_anchor_y || -32;
},
start: function () {
var self = this;
var self_super = this._super;
return this._initDefaultPosition()
.then(function () {
self._initMap();
})
.then(function () {
return self_super.apply(self, arguments);
});
},
_render: function () {
var self = this;
// First remove previous layer that contains
// all the previously rendered records
if (this.leaflet_layer_group) {
this.leaflet_map.removeLayer(this.leaflet_layer_group);
}
// Create a new layer and render fresh records
this.leaflet_layer_group = L.layerGroup().addTo(this.leaflet_map);
_.each(this.state.data, function (record) {
self._renderRecord(record);
});
// Delay and call invalidateSize() to display correctly
// the map. See.
// https://github.com/Leaflet/Leaflet/issues/3002#issuecomment-93836022
return this._super.apply(this, arguments).then(function () {
window.setTimeout(function () {
self.leaflet_map.invalidateSize();
}, 1);
});
},
_renderRecord: function (record) {
var self = this;
var latlng = L.latLng(
record.data[this.field_latitude],
record.data[this.field_longitude]
);
// Display only records that have a valid position
if (latlng.lat !== 0 && latlng.lng !== 0) {
// Create marker
var markerOptions = this._prepareMarkerOptions(record);
var marker = L.marker(latlng, markerOptions).addTo(
this.leaflet_layer_group
);
// Create Popup and attach an event onclick
var popup = L.popup().setContent(this._preparePopUpData(record));
marker.bindPopup(popup).on("popupopen", () => {
$(".o_map_selector").parent().parent().click(
{
model_name: record.model,
res_id: record.data.id,
current_object: self,
},
self._onClickLeafletPopup
);
});
}
},
_onClickLeafletPopup: function (ev) {
ev.preventDefault();
ev.data.current_object.trigger_up("switch_view", {
view_type: "form",
res_id: ev.data.res_id,
model: ev.data.model_name,
});
},
_prepareMarkerIcon: function (record) {
var myIcon = L.icon({
iconUrl: session.url("/web/image", {
model: record.model,
id: JSON.stringify(record.data.id),
field: this.field_marker_icon_image,
// Unique forces a reload of the image when the record has been updated
unique: field_utils.format
.datetime(record.data.__last_update)
.replace(/[^0-9]/g, ""),
}),
className: "leaflet_marker_icon",
iconSize: [this.marker_icon_size_x, this.marker_icon_size_y],
popupAnchor: [this.marker_popup_anchor_x, this.marker_popup_anchor_y],
});
return myIcon;
},
_prepareMarkerOptions: function (record) {
var icon = this._prepareMarkerIcon(record);
var result = {
title: record.data[this.field_title],
alt: record.data[this.field_title],
riseOnHover: true,
};
if (icon) {
result.icon = icon;
}
return result;
},
_preparePopUpData: function (record) {
return (
"<div class='o_map_selector' res_id='" +
record.data.id +
"'>" +
"<b>" +
record.data[this.field_title] +
"</b><br/>" +
" - " +
record.data[this.field_address] +
"</div>"
);
},
_initDefaultPosition: function () {
var self = this;
return this._rpc({
model: "res.users",
method: "get_default_leaflet_position",
args: [this.state.model],
}).then(function (result) {
self.default_lat_lng = L.latLng(result.lat, result.lng);
});
},
_initMap: function () {
var $mainDiv = $("<div id='div_map' class='o_leaflet_map_container'/>");
this.leaflet_container = $mainDiv[0];
this.leaflet_map = L.map(this.leaflet_container, {
zoomSnap: this.zoom_snap,
}).setView(this.default_lat_lng, this.default_zoom);
this.leaflet_tiles = L.tileLayer(this.leaflet_tile_url, {
maxZoom: this.max_zoom,
attribution: this.leaflet_copyright,
}).addTo(this.leaflet_map);
this.$el.append($mainDiv);
},
});
return MapRenderer;
});

View file

@ -0,0 +1,34 @@
odoo.define("web_view_leaflet_map.MapView", function (require) {
"use strict";
var BasicView = require("web.BasicView");
var core = require("web.core");
var MapRenderer = require("web_view_leaflet_map.MapRenderer");
var _lt = core._lt;
var MapView = BasicView.extend({
accesskey: "m",
display_name: _lt("Map"),
icon: "fa fa-map-o",
config: _.extend({}, BasicView.prototype.config, {
Renderer: MapRenderer,
}),
viewType: "leaflet_map",
searchMenuTypes: ["filter", "favorite"],
init: function (viewInfo, params) {
this._super.apply(this, arguments);
var mode =
this.arch.attrs.editable && !params.readonly ? "edit" : "readonly";
this.controllerParams.mode = mode;
this.rendererParams.arch = this.arch;
this.loadParams.limit = this.loadParams.limit || 80;
this.loadParams.type = "list";
},
});
return MapView;
});

View file

@ -0,0 +1,8 @@
odoo.define("web_view_leaflet_map.view_registry", function (require) {
"use strict";
var MapView = require("web_view_leaflet_map.MapView");
var view_registry = require("web.view_registry");
view_registry.add("leaflet_map", MapView);
});