odoo-addon-web-view-leaflet-map 16.0.2.0.0.1__py3-none-any.whl → 18.0.1.0.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. odoo/addons/web_view_leaflet_map/README.rst +74 -76
  2. odoo/addons/web_view_leaflet_map/__manifest__.py +4 -5
  3. odoo/addons/web_view_leaflet_map/hooks.py +4 -4
  4. odoo/addons/web_view_leaflet_map/i18n/fr.po +1 -0
  5. odoo/addons/web_view_leaflet_map/i18n/it.po +1 -0
  6. odoo/addons/web_view_leaflet_map/i18n/web_view_leaflet_map.pot +1 -8
  7. odoo/addons/web_view_leaflet_map/models/ir_ui_view.py +3 -0
  8. odoo/addons/web_view_leaflet_map/readme/CONFIGURE.md +1 -0
  9. odoo/addons/web_view_leaflet_map/readme/CONTRIBUTORS.md +1 -0
  10. odoo/addons/web_view_leaflet_map/readme/DESCRIPTION.md +13 -0
  11. odoo/addons/web_view_leaflet_map/readme/DEVELOP.md +53 -0
  12. odoo/addons/web_view_leaflet_map/readme/ROADMAP.md +8 -0
  13. odoo/addons/web_view_leaflet_map/static/description/index.html +82 -92
  14. odoo/addons/web_view_leaflet_map/static/src/components/map-component/map_view.esm.js +329 -0
  15. odoo/addons/web_view_leaflet_map/static/src/components/map-component/map_view.xml +19 -0
  16. {odoo_addon_web_view_leaflet_map-16.0.2.0.0.1.dist-info → odoo_addon_web_view_leaflet_map-18.0.1.0.0.3.dist-info}/METADATA +81 -82
  17. odoo_addon_web_view_leaflet_map-18.0.1.0.0.3.dist-info/RECORD +26 -0
  18. {odoo_addon_web_view_leaflet_map-16.0.2.0.0.1.dist-info → odoo_addon_web_view_leaflet_map-18.0.1.0.0.3.dist-info}/WHEEL +1 -1
  19. odoo_addon_web_view_leaflet_map-18.0.1.0.0.3.dist-info/top_level.txt +1 -0
  20. odoo/addons/web_view_leaflet_map/readme/CONFIGURE.rst +0 -1
  21. odoo/addons/web_view_leaflet_map/readme/CONTRIBUTORS.rst +0 -1
  22. odoo/addons/web_view_leaflet_map/readme/DESCRIPTION.rst +0 -11
  23. odoo/addons/web_view_leaflet_map/readme/DEVELOP.rst +0 -62
  24. odoo/addons/web_view_leaflet_map/readme/ROADMAP.rst +0 -8
  25. odoo/addons/web_view_leaflet_map/static/src/js/view/map/map_renderer.js +0 -178
  26. odoo/addons/web_view_leaflet_map/static/src/js/view/map/map_view.js +0 -34
  27. odoo/addons/web_view_leaflet_map/static/src/js/view/view_registry.js +0 -8
  28. odoo_addon_web_view_leaflet_map-16.0.2.0.0.1.dist-info/RECORD +0 -27
  29. odoo_addon_web_view_leaflet_map-16.0.2.0.0.1.dist-info/top_level.txt +0 -1
  30. /odoo/addons/web_view_leaflet_map/static/src/{css → components/map-component}/web_view_leaflet_map.css +0 -0
@@ -2,19 +2,18 @@
2
2
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3
3
  <head>
4
4
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
- <meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
5
+ <meta name="generator" content="Docutils: http://docutils.sourceforge.net/" />
6
6
  <title>Leaflet Map View (OpenStreetMap)</title>
7
7
  <style type="text/css">
8
8
 
9
9
  /*
10
10
  :Author: David Goodger (goodger@python.org)
11
- :Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
11
+ :Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
12
12
  :Copyright: This stylesheet has been placed in the public domain.
13
13
 
14
14
  Default cascading style sheet for the HTML output of Docutils.
15
- Despite the name, some widely supported CSS2 features are used.
16
15
 
17
- See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
16
+ See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
18
17
  customize this style sheet.
19
18
  */
20
19
 
@@ -275,7 +274,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
275
274
  margin-left: 2em ;
276
275
  margin-right: 2em }
277
276
 
278
- pre.code .ln { color: gray; } /* line numbers */
277
+ pre.code .ln { color: grey; } /* line numbers */
279
278
  pre.code, code { background-color: #eeeeee }
280
279
  pre.code .comment, code .comment { color: #5C6576 }
281
280
  pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -301,7 +300,7 @@ span.option {
301
300
  span.pre {
302
301
  white-space: pre }
303
302
 
304
- span.problematic, pre.problematic {
303
+ span.problematic {
305
304
  color: red }
306
305
 
307
306
  span.section-subtitle {
@@ -367,21 +366,20 @@ ul.auto-toc {
367
366
  !! This file is generated by oca-gen-addon-readme !!
368
367
  !! changes will be overwritten. !!
369
368
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
370
- !! source digest: sha256:f494ec35cbd29ae4bcc5e46a7a30bf5b2261bd449a3b0ba08a95a70d45dbea12
369
+ !! source digest: sha256:52ae60ed2032c73f0ba6fc8ca70e2a2fc73bb12745aeeda793042efb1175c1b9
371
370
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
372
- <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>
373
- <p>This module extends odoo views, to add a new kind of view, named <tt class="docutils literal">leaflet_map</tt>
374
- that is using the Leaflet javascript library to use maps. (<a class="reference external" href="https://leafletjs.com/">https://leafletjs.com/</a>)
375
- 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>
376
- <p>You can see a simple usage in the module <tt class="docutils literal">web_view_leaflet_map_partner</tt> in the
377
- same OCA repository that displays your contact in a map, if latitude and longitude are
378
- defined. (To define latitude and longitude, refer to the Odoo module <tt class="docutils literal">base_geolocalize</tt>)</p>
379
- <div class="figure">
380
- <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" />
381
- </div>
382
- <div class="figure">
383
- <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" />
384
- </div>
371
+ <p><a class="reference external" 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" 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" href="https://github.com/OCA/geospatial/tree/18.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" href="https://translation.odoo-community.org/projects/geospatial-18-0/geospatial-18-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" href="https://runboat.odoo-community.org/builds?repo=OCA/geospatial&amp;target_branch=18.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
372
+ <p>This module extends odoo views, to add a new kind of view, named
373
+ <tt class="docutils literal">leaflet_map</tt> that is using the Leaflet javascript library to use
374
+ maps. (<a class="reference external" href="https://leafletjs.com/">https://leafletjs.com/</a>) This library is for exemple, used in the
375
+ OpenStreetMap project. (<a class="reference external" href="https://www.openstreetmap.org/">https://www.openstreetmap.org/</a>)</p>
376
+ <p>You can see a simple usage in the module
377
+ <tt class="docutils literal">web_view_leaflet_map_partner</tt> in the same OCA repository that
378
+ displays your contact in a map, if latitude and longitude are defined.
379
+ (To define latitude and longitude, refer to the Odoo module
380
+ <tt class="docutils literal">base_geolocalize</tt>)</p>
381
+ <p><img alt="image1" src="https://raw.githubusercontent.com/OCA/geospatial/18.0/web_view_leaflet_map/static/description/view_res_partner_map_1.png" /></p>
382
+ <p><img alt="image2" src="https://raw.githubusercontent.com/OCA/geospatial/18.0/web_view_leaflet_map/static/description/view_res_partner_map_2.png" /></p>
385
383
  <div class="admonition important">
386
384
  <p class="first admonition-title">Important</p>
387
385
  <p class="last">This is an alpha version, the data model and design can change at any time without warning.
@@ -391,131 +389,123 @@ Only for development or testing purpose, do not use in production.
391
389
  <p><strong>Table of contents</strong></p>
392
390
  <div class="contents local topic" id="contents">
393
391
  <ul class="simple">
394
- <li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
395
- <li><a class="reference internal" href="#development" id="toc-entry-2">Development</a></li>
396
- <li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-3">Known issues / Roadmap</a></li>
397
- <li><a class="reference internal" href="#bug-tracker" id="toc-entry-4">Bug Tracker</a></li>
398
- <li><a class="reference internal" href="#credits" id="toc-entry-5">Credits</a><ul>
399
- <li><a class="reference internal" href="#authors" id="toc-entry-6">Authors</a></li>
400
- <li><a class="reference internal" href="#contributors" id="toc-entry-7">Contributors</a></li>
401
- <li><a class="reference internal" href="#maintainers" id="toc-entry-8">Maintainers</a></li>
392
+ <li><a class="reference internal" href="#configuration" id="id1">Configuration</a></li>
393
+ <li><a class="reference internal" href="#development" id="id2">Development</a></li>
394
+ <li><a class="reference internal" href="#known-issues-roadmap" id="id3">Known issues / Roadmap</a></li>
395
+ <li><a class="reference internal" href="#bug-tracker" id="id4">Bug Tracker</a></li>
396
+ <li><a class="reference internal" href="#credits" id="id5">Credits</a><ul>
397
+ <li><a class="reference internal" href="#authors" id="id6">Authors</a></li>
398
+ <li><a class="reference internal" href="#contributors" id="id7">Contributors</a></li>
399
+ <li><a class="reference internal" href="#maintainers" id="id8">Maintainers</a></li>
402
400
  </ul>
403
401
  </li>
404
402
  </ul>
405
403
  </div>
406
404
  <div class="section" id="configuration">
407
- <h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
405
+ <h1><a class="toc-backref" href="#id1">Configuration</a></h1>
408
406
  <ul class="simple">
409
407
  <li>See configuration of the module <tt class="docutils literal">web_leaflet_lib</tt>.</li>
410
408
  </ul>
411
409
  </div>
412
410
  <div class="section" id="development">
413
- <h1><a class="toc-backref" href="#toc-entry-2">Development</a></h1>
411
+ <h1><a class="toc-backref" href="#id2">Development</a></h1>
414
412
  <p>Create a new view :</p>
415
413
  <pre class="code xml literal-block">
416
- <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">
417
- </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">
418
- </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">
419
- </span><span class="nt">&lt;leaflet_map</span><span class="w">
420
- </span><span class="na">field_latitude=</span><span class="s">&quot;FIELD_LATITUDE&quot;</span><span class="w">
421
- </span><span class="na">field_longitude=</span><span class="s">&quot;FIELD_LONGITUDE&quot;</span><span class="w">
422
- </span><span class="na">field_title=</span><span class="s">&quot;FIELD_TITLE&quot;</span><span class="w">
423
- </span><span class="na">field_address=</span><span class="s">&quot;FIELD_ADDRESS&quot;</span><span class="w">
424
- </span><span class="na">field_marker_icon_image=</span><span class="s">&quot;FIELD_MARKER_ICON_IMAGE&quot;</span><span class="w">
425
- </span><span class="nt">&gt;</span><span class="w">
426
- </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">
427
- </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">
428
- </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">
429
- </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">
430
- </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">
431
- </span><span class="nt">&lt;/leaflet_map&gt;</span><span class="w">
432
- </span><span class="nt">&lt;/field&gt;</span><span class="w">
433
- </span><span class="nt">&lt;/record&gt;</span>
414
+ <span class="nt">&lt;record</span> <span class="na">id=</span><span class="s">&quot;view_my_model_map&quot;</span> <span class="na">model=</span><span class="s">&quot;ir.ui.view&quot;</span><span class="nt">&gt;</span>
415
+ <span class="nt">&lt;field</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>
416
+ <span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">&quot;arch&quot;</span> <span class="na">type=</span><span class="s">&quot;xml&quot;</span><span class="nt">&gt;</span>
417
+ <span class="nt">&lt;leaflet_map</span>
418
+ <span class="na">field_latitude=</span><span class="s">&quot;FIELD_LATITUDE&quot;</span>
419
+ <span class="na">field_longitude=</span><span class="s">&quot;FIELD_LONGITUDE&quot;</span>
420
+ <span class="na">field_title=</span><span class="s">&quot;FIELD_TITLE&quot;</span>
421
+ <span class="na">field_address=</span><span class="s">&quot;FIELD_ADDRESS&quot;</span>
422
+ <span class="na">field_marker_icon_image=</span><span class="s">&quot;FIELD_MARKER_ICON_IMAGE&quot;</span>
423
+ <span class="nt">&gt;</span>
424
+ <span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">&quot;__last_update&quot;</span><span class="nt">/&gt;</span>
425
+ <span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">&quot;FIELD_LATITUDE&quot;</span><span class="nt">/&gt;</span>
426
+ <span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">&quot;FIELD_LONGITUDE&quot;</span><span class="nt">/&gt;</span>
427
+ <span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">&quot;FIELD_TITLE&quot;</span><span class="nt">/&gt;</span>
428
+ <span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">&quot;FIELD_ADDRESS&quot;</span><span class="nt">/&gt;</span>
429
+ <span class="nt">&lt;/leaflet_map&gt;</span>
430
+ <span class="nt">&lt;/field&gt;</span>
431
+ <span class="nt">&lt;/record&gt;</span>
434
432
  </pre>
435
433
  <ol class="arabic simple">
436
- <li>FIELD_LATITUDE and FIELD_LONGITUDE are the name of the fields that contains GPS coordinates of the model.</li>
434
+ <li>FIELD_LATITUDE and FIELD_LONGITUDE are the name of the fields that
435
+ contains GPS coordinates of the model.</li>
437
436
  <li>FIELD_TITLE will be used when the popup is displayed, as a title.</li>
438
- <li>FIELD_ADDRESS will be used when the popup is displayed to display the adress.</li>
439
- <li>(optional) FIELD_MARKER_ICON_IMAGE, is the name of the image field to place as an icon
440
- of the marker.
441
- 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
442
- 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
443
- the position of the popup.</li>
437
+ <li>FIELD_ADDRESS will be used when the popup is displayed to display the
438
+ adress.</li>
439
+ <li>(optional) FIELD_MARKER_ICON_IMAGE, is the name of the image field to
440
+ place as an icon of the marker. Note: You can set extra settings
441
+ <tt class="docutils literal">marker_icon_size_x</tt>, <tt class="docutils literal">marker_icon_size_y</tt>, to define the size of
442
+ the image, and <tt class="docutils literal">marker_popup_anchor_x</tt>, <tt class="docutils literal">marker_popup_anchor_y</tt>
443
+ to define the position of the popup.</li>
444
444
  </ol>
445
445
  <p>Map options :</p>
446
446
  <ul class="simple">
447
447
  <li><tt class="docutils literal">default_zoom</tt> : define the default zoom value. (7 if not defined)</li>
448
448
  <li><tt class="docutils literal">max_zoom</tt> : define the max zoom value. (19 if not defined)</li>
449
- <li><tt class="docutils literal">zoom_snap</tt> : define the zoom level in each change. (1 if not defined)</li>
450
- </ul>
451
- <ul class="simple">
449
+ <li><tt class="docutils literal">zoom_snap</tt> : define the zoom level in each change. (1 if not
450
+ defined)</li>
452
451
  <li>Create or update an action for the model</li>
453
452
  </ul>
454
453
  <pre class="code xml literal-block">
455
- <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">
456
- </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">
457
- </span><span class="nt">&lt;/record&gt;</span>
454
+ <span class="nt">&lt;record</span> <span class="na">id=</span><span class="s">&quot;my_module.action_my_model&quot;</span> <span class="na">model=</span><span class="s">&quot;ir.actions.act_window&quot;</span><span class="nt">&gt;</span>
455
+ <span class="nt">&lt;field</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>
456
+ <span class="nt">&lt;/record&gt;</span>
458
457
  </pre>
459
- <p><strong>Library Update</strong></p>
460
- <p>For the time being, the module embed the lealflet.js library version 1.8.0 ( released on April 18, 2022.)</p>
461
- <p>If a new release is out:</p>
462
- <ul class="simple">
463
- <li>please download it here <a class="reference external" href="https://leafletjs.com/download.html">https://leafletjs.com/download.html</a></li>
464
- <li>update the javascript, css and images, present in the folder <tt class="docutils literal">static/lib/leaflet</tt></li>
465
- <li>test the features</li>
466
- <li>make a Pull Request</li>
467
- </ul>
468
458
  <p><strong>Default position in the map</strong></p>
469
- <p>By default, the position of the map is defined by the user, in the function
470
- <tt class="docutils literal">get_default_leaflet_position</tt>. It returns the position of the current company, if defined.
471
- you can overload this function globally, or per model.</p>
459
+ <p>By default, the position of the map is defined by the user, in the
460
+ function <tt class="docutils literal">get_default_leaflet_position</tt>. It returns the position of
461
+ the current company, if defined. you can overload this function
462
+ globally, or per model.</p>
472
463
  </div>
473
464
  <div class="section" id="known-issues-roadmap">
474
- <h1><a class="toc-backref" href="#toc-entry-3">Known issues / Roadmap</a></h1>
465
+ <h1><a class="toc-backref" href="#id3">Known issues / Roadmap</a></h1>
475
466
  <ul class="simple">
476
- <li>For the time being, at the start of the map loading, the call of <tt class="docutils literal">invalidateSize()</tt>
477
- is required. We should investigate why and try to remove that call.
478
- 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>
479
- <li>For the time being, the map has “Markers” and allow to display odoo items
480
- if longitude and latitude are available. We could imagine other kind of usages,
481
- with Polylines, Polygons, etc…
482
- See all the leaflet options : <a class="reference external" href="https://leafletjs.com/reference.html">https://leafletjs.com/reference.html</a></li>
467
+ <li>For the time being, at the start of the map loading, the call of
468
+ <tt class="docutils literal">invalidateSize()</tt> is required. We should investigate why and try to
469
+ remove that call. see
470
+ <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>
471
+ <li>For the time being, the map has “Markers” and allow to display odoo
472
+ items if longitude and latitude are available. We could imagine other
473
+ kind of usages, with Polylines, Polygons, etc… See all the leaflet
474
+ options : <a class="reference external" href="https://leafletjs.com/reference.html">https://leafletjs.com/reference.html</a></li>
483
475
  </ul>
484
476
  </div>
485
477
  <div class="section" id="bug-tracker">
486
- <h1><a class="toc-backref" href="#toc-entry-4">Bug Tracker</a></h1>
478
+ <h1><a class="toc-backref" href="#id4">Bug Tracker</a></h1>
487
479
  <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/geospatial/issues">GitHub Issues</a>.
488
480
  In case of trouble, please check there if your issue has already been reported.
489
481
  If you spotted it first, help us to smash it by providing a detailed and welcomed
490
- <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>
482
+ <a class="reference external" href="https://github.com/OCA/geospatial/issues/new?body=module:%20web_view_leaflet_map%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
491
483
  <p>Do not contact contributors directly about support or help with technical issues.</p>
492
484
  </div>
493
485
  <div class="section" id="credits">
494
- <h1><a class="toc-backref" href="#toc-entry-5">Credits</a></h1>
486
+ <h1><a class="toc-backref" href="#id5">Credits</a></h1>
495
487
  <div class="section" id="authors">
496
- <h2><a class="toc-backref" href="#toc-entry-6">Authors</a></h2>
488
+ <h2><a class="toc-backref" href="#id6">Authors</a></h2>
497
489
  <ul class="simple">
498
490
  <li>GRAP</li>
499
491
  </ul>
500
492
  </div>
501
493
  <div class="section" id="contributors">
502
- <h2><a class="toc-backref" href="#toc-entry-7">Contributors</a></h2>
494
+ <h2><a class="toc-backref" href="#id7">Contributors</a></h2>
503
495
  <ul class="simple">
504
496
  <li>Sylvain LE GAL (<a class="reference external" href="https://www.twitter.com/legalsylvain">https://www.twitter.com/legalsylvain</a>)</li>
505
497
  </ul>
506
498
  </div>
507
499
  <div class="section" id="maintainers">
508
- <h2><a class="toc-backref" href="#toc-entry-8">Maintainers</a></h2>
500
+ <h2><a class="toc-backref" href="#id8">Maintainers</a></h2>
509
501
  <p>This module is maintained by the OCA.</p>
510
- <a class="reference external image-reference" href="https://odoo-community.org">
511
- <img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
512
- </a>
502
+ <a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
513
503
  <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
514
504
  mission is to support the collaborative development of Odoo features and
515
505
  promote its widespread use.</p>
516
506
  <p>Current <a class="reference external" href="https://odoo-community.org/page/maintainer-role">maintainer</a>:</p>
517
- <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>
518
- <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>
507
+ <p><a class="reference external" href="https://github.com/legalsylvain"><img alt="legalsylvain" src="https://github.com/legalsylvain.png?size=40px" /></a></p>
508
+ <p>This module is part of the <a class="reference external" href="https://github.com/OCA/geospatial/tree/18.0/web_view_leaflet_map">OCA/geospatial</a> project on GitHub.</p>
519
509
  <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>
520
510
  </div>
521
511
  </div>
@@ -0,0 +1,329 @@
1
+ import {registry} from "@web/core/registry";
2
+ import {useService} from "@web/core/utils/hooks";
3
+ import {Layout} from "@web/search/layout";
4
+ import {session} from "@web/session";
5
+
6
+ /* global L, console, document, DOMParser */
7
+
8
+ const {Component, useSubEnv, onWillStart, onMounted, onPatched, useRef} = owl;
9
+
10
+ export class MapRenderer extends Component {
11
+ /**
12
+ * Initializes the MapRenderer component, setting up services, references, and configuration.
13
+ */
14
+ setup() {
15
+ console.log(this.props);
16
+ this.orm = useService("orm");
17
+ this.action = useService("action");
18
+ this.mapRef = useRef("mapContainer");
19
+ this.leafletTileUrl = session["leaflet.tile_url"];
20
+ this.leafletCopyright = session["leaflet.copyright"];
21
+
22
+ const archAttrs = this.props.archInfo.arch.attributes;
23
+
24
+ this.resModel = this.props.resModel;
25
+ this.defaultZoom = parseInt(archAttrs.default_zoom, 10) || 7;
26
+ this.maxZoom = parseInt(archAttrs.max_zoom, 10) || 19;
27
+ this.zoomSnap = parseInt(archAttrs.zoom_snap, 10) || 1;
28
+
29
+ this.fieldLatitude = archAttrs.field_latitude?.value;
30
+ this.fieldLongitude = archAttrs.field_longitude?.value;
31
+ this.fieldTitle = archAttrs.field_title?.value;
32
+ this.fieldAddress = archAttrs.field_address?.value;
33
+ this.fieldMarkerIconImage = archAttrs.field_marker_icon_image?.value;
34
+
35
+ this.markerIconSizeX = parseInt(archAttrs.marker_icon_size_x?.value, 10) || 64;
36
+ this.markerIconSizeY = parseInt(archAttrs.marker_icon_size_y?.value, 10) || 64;
37
+ this.markerPopupAnchorX =
38
+ parseInt(archAttrs.marker_popup_anchor_x?.value, 10) || 0;
39
+ this.markerPopupAnchorY =
40
+ parseInt(archAttrs.marker_popup_anchor_y?.value, 10) || -32;
41
+
42
+ this.leafletMap = null;
43
+ this.leafletFeatureGroup = null;
44
+
45
+ onWillStart(async () => {
46
+ await this.initDefaultPosition();
47
+ await this.loadRecords();
48
+ });
49
+
50
+ onMounted(() => {
51
+ this.initMap();
52
+ this.renderMarkers();
53
+ });
54
+
55
+ onPatched(() => {
56
+ console.log("onPatched");
57
+ if (this.leafletMap) {
58
+ this.renderMarkers();
59
+ }
60
+ });
61
+ }
62
+
63
+ /**
64
+ * Loads records from the server based on the provided domain and fields.
65
+ * @returns {Promise<void>}
66
+ */
67
+ async loadRecords() {
68
+ const fields = this.getFields();
69
+
70
+ try {
71
+ // Cargar registros usando searchRead
72
+ const records = await this.orm.searchRead(
73
+ this.resModel,
74
+ this.props.domain || [],
75
+ fields,
76
+ {
77
+ limit: this.props.limit || 80,
78
+ context: this.props.context || {},
79
+ }
80
+ );
81
+ this.records = records;
82
+ } catch (error) {
83
+ console.error("Error loading records:", error);
84
+ this.records = [];
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Gathers the required fields for the map view.
90
+ * @returns {any[]}
91
+ */
92
+ getFields() {
93
+ const fields = new Set();
94
+
95
+ // Required fields
96
+ fields.add("id");
97
+ fields.add("display_name");
98
+ fields.add("date_localization");
99
+
100
+ // Optional fields based on arch attributes
101
+ if (this.fieldLatitude) fields.add(this.fieldLatitude);
102
+ if (this.fieldLongitude) fields.add(this.fieldLongitude);
103
+ if (this.fieldTitle) fields.add(this.fieldTitle);
104
+ if (this.fieldAddress) fields.add(this.fieldAddress);
105
+ if (this.fieldMarkerIconImage) fields.add(this.fieldMarkerIconImage);
106
+
107
+ return Array.from(fields);
108
+ }
109
+
110
+ /**
111
+ * Initializes the default position of the map by calling the server method.
112
+ * @returns {Promise<void>}
113
+ */
114
+ async initDefaultPosition() {
115
+ const result = await this.orm.call(
116
+ "res.users",
117
+ "get_default_leaflet_position",
118
+ [this.props.resModel]
119
+ );
120
+ this.defaultLatLng = L.latLng(result.lat, result.lng);
121
+ }
122
+
123
+ /**
124
+ * Initializes the Leaflet map in the container.
125
+ */
126
+ initMap() {
127
+ const mapDiv = this.mapRef.el;
128
+ if (!mapDiv) {
129
+ console.error("Map container not found");
130
+ return;
131
+ }
132
+
133
+ this.leafletMap = L.map(mapDiv, {
134
+ zoomSnap: this.zoomSnap,
135
+ }).setView(this.defaultLatLng, this.defaultZoom);
136
+
137
+ L.tileLayer(this.leafletTileUrl, {
138
+ maxZoom: this.maxZoom,
139
+ attribution: this.leafletCopyright,
140
+ }).addTo(this.leafletMap);
141
+ }
142
+
143
+ /**
144
+ * Renders the markers on the map based on the loaded records.
145
+ */
146
+ renderMarkers() {
147
+ if (!this.leafletMap) {
148
+ console.warn("Map not initialized yet");
149
+ return;
150
+ }
151
+
152
+ if (this.leafletFeatureGroup) {
153
+ this.leafletMap.removeLayer(this.leafletFeatureGroup);
154
+ }
155
+
156
+ this.leafletFeatureGroup = L.featureGroup().addTo(this.leafletMap);
157
+
158
+ for (const record of this.records) {
159
+ const marker = this.prepareMarker(record);
160
+ if (marker) {
161
+ marker.addTo(this.leafletFeatureGroup);
162
+ }
163
+ }
164
+
165
+ this.leafletMap.fitBounds(this.leafletFeatureGroup.getBounds().pad(0.1));
166
+ }
167
+
168
+ /**
169
+ * Prepares a Leaflet marker for the given record.
170
+ * @param {Object} record - The record object containing marker data
171
+ * @returns {*}
172
+ */
173
+ prepareMarker(record) {
174
+ const lat = record[this.fieldLatitude];
175
+ const lng = record[this.fieldLongitude];
176
+ let marker = null;
177
+ if (!lat || !lng) {
178
+ console.log(`Record ${record.id} has no coordinates`);
179
+ return;
180
+ }
181
+
182
+ const latlng = L.latLng(lat, lng);
183
+ if (latlng.lat !== 0 && latlng.lng !== 0) {
184
+ const markerOptions = this.prepareMarkerOptions(record);
185
+
186
+ marker = L.marker(latlng, markerOptions);
187
+ const popup = L.popup().setContent(this.preparePopUpData(record));
188
+
189
+ marker.bindPopup(popup).on("popupopen", () => {
190
+ const selector = document.querySelector(".o_map_selector");
191
+ if (selector) {
192
+ selector.addEventListener("click", (ev) => {
193
+ ev.preventDefault();
194
+ this.onClickLeafletPopup(record);
195
+ });
196
+ }
197
+ });
198
+
199
+ return marker;
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Prepares the Leaflet icon for the marker using the image field.
205
+ * @param {Object} record - The record object containing marker data
206
+ * @returns {*}
207
+ */
208
+ prepareMarkerIcon(record) {
209
+ const lastUpdate = record.date_localization || new Date().toISOString();
210
+ const unique = lastUpdate.replace(/[^0-9]/g, "");
211
+ const iconUrl = `/web/image?model=${this.resModel}&id=${record.id}&field=${this.fieldMarkerIconImage}&unique=${unique}`;
212
+
213
+ return L.icon({
214
+ iconUrl: iconUrl,
215
+ className: "leaflet_marker_icon",
216
+ iconSize: [this.markerIconSizeX, this.markerIconSizeY],
217
+ popupAnchor: [this.markerPopupAnchorX, this.markerPopupAnchorY],
218
+ });
219
+ }
220
+
221
+ /**
222
+ * Prepares the options for the leaflet marker.
223
+ * @param {Object} record - The record object containing marker data
224
+ * @returns {{riseOnHover: Boolean, alt: (*|string), title: (*|string)}}
225
+ */
226
+ prepareMarkerOptions(record) {
227
+ const title = record[this.fieldTitle] || "";
228
+ const result = {
229
+ title: title,
230
+ alt: title,
231
+ riseOnHover: true,
232
+ };
233
+
234
+ if (this.fieldMarkerIconImage) {
235
+ result.icon = this.prepareMarkerIcon(record);
236
+ }
237
+
238
+ return result;
239
+ }
240
+
241
+ /**
242
+ * Prepares the HTML content for the leaflet popup.
243
+ * @param {Object} record - The record object containing marker data
244
+ * @returns {String}
245
+ */
246
+ preparePopUpData(record) {
247
+ const title = record[this.fieldTitle] || "";
248
+ const address = record[this.fieldAddress] || "";
249
+
250
+ return `
251
+ <div class='o_map_selector' data-res-id='${record.resId}'>
252
+ <b>${title}</b><br/>
253
+ ${address ? ` - ${address}` : ""}
254
+ </div>
255
+ `;
256
+ }
257
+
258
+ /**
259
+ * Handles click on the leaflet popup to open the record form view.
260
+ * @param {Object} record - The record object containing marker data
261
+ */
262
+ onClickLeafletPopup(record) {
263
+ this.action.doAction({
264
+ type: "ir.actions.act_window",
265
+ res_model: this.resModel,
266
+ res_id: record.id,
267
+ views: [[false, "form"]],
268
+ target: "current",
269
+ });
270
+ }
271
+ }
272
+
273
+ MapRenderer.template = "web_view_leaflet_map.MapRenderer";
274
+ MapRenderer.components = {};
275
+
276
+ /**
277
+ * Controller class for the Map view, setting up the environment configuration.
278
+ */
279
+ export class MapController extends Component {
280
+ setup() {
281
+ useSubEnv({
282
+ config: {
283
+ ...this.env.config,
284
+ },
285
+ });
286
+ }
287
+ }
288
+
289
+ MapController.template = "web_view_leaflet_map.MapView";
290
+ MapController.components = {Layout, MapRenderer};
291
+
292
+ /**
293
+ * Helper function that normalize the architecture input to ensure it is an HTMLElement.
294
+ * @param arch
295
+ * @returns {HTMLElement|*}
296
+ */
297
+ function normalizeArch(arch) {
298
+ if (arch && typeof arch !== "string") return arch;
299
+ const xml = String(arch || "");
300
+ const doc = new DOMParser().parseFromString(xml, "text/xml");
301
+ return doc.documentElement;
302
+ }
303
+
304
+ /**
305
+ * Definition of the map view for Odoo, including its properties and components.
306
+ * @type {{searchMenuTypes: string[], icon: string, Renderer: MapRenderer, multiRecord: boolean, type: string, display_name: string, Controller: MapController, props: (function(*, *): *&{archInfo: {arch: *}, Renderer: MapRenderer})}}
307
+ */
308
+ export const mapView = {
309
+ type: "leaflet_map",
310
+ display_name: "Map",
311
+ icon: "fa fa-map-o",
312
+ multiRecord: true,
313
+ Controller: MapController,
314
+ Renderer: MapRenderer,
315
+ searchMenuTypes: ["filter", "favorite"],
316
+
317
+ props: (genericProps) => {
318
+ const archEl = normalizeArch(genericProps.arch);
319
+ return {
320
+ ...genericProps,
321
+ Renderer: MapRenderer,
322
+ archInfo: {
323
+ arch: archEl,
324
+ },
325
+ };
326
+ },
327
+ };
328
+
329
+ registry.category("views").add("leaflet_map", mapView);
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="UTF-8" ?>
2
+ <templates xml:space="preserve">
3
+
4
+ <t t-name="web_view_leaflet_map.MapView" owl="1">
5
+ <Layout display="props.display" className="'h-100'">
6
+ <t t-set-slot="control-panel-bottom-right">
7
+ <div />
8
+ </t>
9
+ <MapRenderer t-props="props" />
10
+ </Layout>
11
+ </t>
12
+
13
+ <t t-name="web_view_leaflet_map.MapRenderer" owl="1">
14
+ <div class="o_leaflet_main_container h-100">
15
+ <div t-ref="mapContainer" class="o_leaflet_map_container h-100" />
16
+ </div>
17
+ </t>
18
+
19
+ </templates>