mirror of
https://github.com/bringout/oca-technical.git
synced 2026-04-18 04:11:59 +02:00
Initial commit: OCA Technical packages (595 packages)
This commit is contained in:
commit
2cc02aac6e
24950 changed files with 2318079 additions and 0 deletions
|
|
@ -0,0 +1,47 @@
|
|||
# Geospatial Website store locator
|
||||
|
||||
Odoo addon: website_geoengine_store_locator
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install odoo-bringout-oca-geospatial-website_geoengine_store_locator
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
This addon depends on:
|
||||
- base_geoengine
|
||||
- website
|
||||
- partner_store
|
||||
- website_geoengine
|
||||
|
||||
## Manifest Information
|
||||
|
||||
- **Name**: Geospatial Website store locator
|
||||
- **Version**: 16.0.1.0.0
|
||||
- **Category**: GeoBI
|
||||
- **License**: AGPL-3
|
||||
- **Installable**: True
|
||||
|
||||
## Source
|
||||
|
||||
Based on [OCA/geospatial](https://github.com/OCA/geospatial) branch 16.0, addon `website_geoengine_store_locator`.
|
||||
|
||||
## 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
|
||||
|
|
@ -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 Website_geoengine_store_locator Module - website_geoengine_store_locator
|
||||
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.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Configuration
|
||||
|
||||
Refer to Odoo settings for website_geoengine_store_locator. Configure related models, access rights, and options as needed.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Controllers
|
||||
|
||||
This module does not define custom HTTP controllers.
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
# Dependencies
|
||||
|
||||
This addon depends on:
|
||||
|
||||
- [base_geoengine](../../odoo-bringout-oca-geospatial-base_geoengine)
|
||||
- [website](../../odoo-bringout-oca-ocb-website)
|
||||
- partner_store
|
||||
- [website_geoengine](../../odoo-bringout-oca-geospatial-website_geoengine)
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# FAQ
|
||||
|
||||
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
|
||||
- Q: How to enable? A: Start server with --addon website_geoengine_store_locator or install in UI.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# Install
|
||||
|
||||
```bash
|
||||
pip install odoo-bringout-oca-geospatial-website_geoengine_store_locator"
|
||||
# or
|
||||
uv pip install odoo-bringout-oca-geospatial-website_geoengine_store_locator"
|
||||
```
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
# Models
|
||||
|
||||
Detected core models and extensions in website_geoengine_store_locator.
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
```
|
||||
|
||||
Notes
|
||||
- Classes show model technical names; fields omitted for brevity.
|
||||
- Items listed under _inherit are extensions of existing models.
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
# Overview
|
||||
|
||||
Packaged Odoo addon: website_geoengine_store_locator. Provides features documented in upstream Odoo 16 under this addon.
|
||||
|
||||
- Source: OCA/OCB 16.0, addon website_geoengine_store_locator
|
||||
- License: LGPL-3
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Reports
|
||||
|
||||
This module does not define custom reports.
|
||||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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 website_geoengine_store_locator
|
||||
```
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Wizards
|
||||
|
||||
This module does not include UI wizards.
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
[project]
|
||||
name = "odoo-bringout-oca-geospatial-website_geoengine_store_locator"
|
||||
version = "16.0.0"
|
||||
description = "Geospatial Website store locator - Odoo addon"
|
||||
authors = [
|
||||
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
|
||||
]
|
||||
dependencies = [
|
||||
"odoo-bringout-oca-geospatial-base_geoengine>=16.0.0",
|
||||
"odoo-bringout-oca-ocb-website>=16.0.0",
|
||||
"odoo-bringout-oca-geospatial-partner_store>=16.0.0",
|
||||
"odoo-bringout-oca-geospatial-website_geoengine>=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 = ["website_geoengine_store_locator"]
|
||||
|
||||
[tool.rye]
|
||||
managed = true
|
||||
dev-dependencies = [
|
||||
"pytest>=8.4.1",
|
||||
]
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
================================
|
||||
Geospatial Website store locator
|
||||
================================
|
||||
|
||||
..
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:fe322224dbdd376eea03ba9aa37eaf3c4bc975d36a999b33a2f799caf36e441f
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |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/website_geoengine_store_locator
|
||||
: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-website_geoengine_store_locator
|
||||
: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 the ``website_geoengine`` odoo module, to add
|
||||
a map snippet view for the website.
|
||||
By default the map features are filtered to only display contact of type `store`.
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
You should configure first a web site. Then drag n drop the Store Locator widget from the OCA/Geopspatial section.
|
||||
|
||||
.. figure:: https://raw.githubusercontent.com/OCA/geospatial/16.0/website_geoengine_store_locator/static/description/snippet.png
|
||||
|
||||
You can the configure the maximum number of results you want to display before to force your user to filter results.
|
||||
|
||||
.. figure:: https://raw.githubusercontent.com/OCA/geospatial/16.0/website_geoengine_store_locator/static/description/snippet_configuration.png
|
||||
|
||||
Then go to 'Contact' app and add some store type address to your contacts and add them some tags.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
.. figure:: https://raw.githubusercontent.com/OCA/geospatial/16.0/website_geoengine_store_locator/static/description/screencast.gif
|
||||
|
||||
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:%20website_geoengine_store_locator%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
|
||||
~~~~~~~
|
||||
|
||||
* Camptocamp
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Stéphane Brunner <stephane.brunner@camptocamp.com>
|
||||
* Hadrien Huvelle <hadrien.huvelle@camptocamp.com>
|
||||
|
||||
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-Wouitmil| image:: https://github.com/Wouitmil.png?size=40px
|
||||
:target: https://github.com/Wouitmil
|
||||
:alt: Wouitmil
|
||||
|
||||
Current `maintainer <https://odoo-community.org/page/maintainer-role>`__:
|
||||
|
||||
|maintainer-Wouitmil|
|
||||
|
||||
This module is part of the `OCA/geospatial <https://github.com/OCA/geospatial/tree/16.0/website_geoengine_store_locator>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
# Copyright 2024 Camptocamp
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
{
|
||||
"name": "Geospatial Website store locator",
|
||||
"version": "16.0.1.0.0",
|
||||
"category": "GeoBI",
|
||||
"author": "Camptocamp, Odoo Community Association (OCA)",
|
||||
"license": "AGPL-3",
|
||||
"website": "https://github.com/OCA/geospatial",
|
||||
"depends": ["base_geoengine", "website", "partner_store", "website_geoengine"],
|
||||
"data": [
|
||||
"templates/snippets/s_openlayer_store_locator.xml",
|
||||
"views/snippets.xml",
|
||||
],
|
||||
"assets": {
|
||||
"web.assets_frontend": [
|
||||
"website_geoengine_store_locator/static/lib/node_modules/ol/dist/ol.js",
|
||||
(
|
||||
"website_geoengine_store_locator/static/lib/node_modules/"
|
||||
"jquery-flexdatalist/jquery.flexdatalist.js"
|
||||
),
|
||||
(
|
||||
"website_geoengine_store_locator/static/src/scss/snippets/"
|
||||
"s_openlayer_store_locator/frontend.scss"
|
||||
),
|
||||
(
|
||||
"website_geoengine_store_locator/static/src/js/snippets/"
|
||||
"s_openlayer_store_locator/frontend.esm.js"
|
||||
),
|
||||
(
|
||||
"website_geoengine_store_locator/static/src/js/snippets/"
|
||||
"s_openlayer_store_locator/popover.esm.js"
|
||||
),
|
||||
(
|
||||
"website_geoengine_store_locator/static/src/js/snippets/"
|
||||
"s_openlayer_store_locator/search.esm.js"
|
||||
),
|
||||
(
|
||||
"website_geoengine_store_locator/static/src/js/snippets/"
|
||||
"s_openlayer_store_locator/map.esm.js"
|
||||
),
|
||||
"/web/static/lib/stacktracejs/stacktrace.js",
|
||||
],
|
||||
"website.assets_wysiwyg": [
|
||||
(
|
||||
"website_geoengine_store_locator/static/src/js/snippets/"
|
||||
"s_openlayer_store_locator/snippet.options.esm.js"
|
||||
)
|
||||
],
|
||||
},
|
||||
"maintainers": ["Wouitmil"],
|
||||
"installable": True,
|
||||
"application": True,
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * website_geoengine_store_locator
|
||||
#
|
||||
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: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.s_openlayer_store_locator_options
|
||||
msgid "200"
|
||||
msgstr "Validacija ${object.company_id.name} foruma"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.s_openlayer_store_locator_options
|
||||
msgid "Max number of results"
|
||||
msgstr "Maksimalni broj rezultata"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.website_geoengine_store_locator_snipet
|
||||
msgid "OCA/Geospatial"
|
||||
msgstr "OCA/Geospatial"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.s_openlayer_store_locator
|
||||
msgid "Search store"
|
||||
msgstr "Pretraži prodavnicu"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.website_geoengine_store_locator_snipet
|
||||
msgid "Store Locator"
|
||||
msgstr "Locator prodavnica"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.website_geoengine_store_locator_snipet
|
||||
msgid "map, store"
|
||||
msgstr "mapa, prodavnica"
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * website_geoengine_store_locator
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 16.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2024-11-03 17:06+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 5.6.2\n"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.s_openlayer_store_locator_options
|
||||
msgid "200"
|
||||
msgstr "200"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.s_openlayer_store_locator_options
|
||||
msgid "Max number of results"
|
||||
msgstr "Numero massimo risultati"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.website_geoengine_store_locator_snipet
|
||||
msgid "OCA/Geospatial"
|
||||
msgstr "OCA/Geospaziali"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.s_openlayer_store_locator
|
||||
msgid "Search store"
|
||||
msgstr "Cerca deposito"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.website_geoengine_store_locator_snipet
|
||||
msgid "Store Locator"
|
||||
msgstr "Localizzatore deposito"
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.website_geoengine_store_locator_snipet
|
||||
msgid "map, store"
|
||||
msgstr "mappa, deposito"
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * website_geoengine_store_locator
|
||||
#
|
||||
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: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.s_openlayer_store_locator_options
|
||||
msgid "200"
|
||||
msgstr ""
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.s_openlayer_store_locator_options
|
||||
msgid "Max number of results"
|
||||
msgstr ""
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.website_geoengine_store_locator_snipet
|
||||
msgid "OCA/Geospatial"
|
||||
msgstr ""
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.s_openlayer_store_locator
|
||||
msgid "Search store"
|
||||
msgstr ""
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.website_geoengine_store_locator_snipet
|
||||
msgid "Store Locator"
|
||||
msgstr ""
|
||||
|
||||
#. module: website_geoengine_store_locator
|
||||
#: model_terms:ir.ui.view,arch_db:website_geoengine_store_locator.website_geoengine_store_locator_snipet
|
||||
msgid "map, store"
|
||||
msgstr ""
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
You should configure first a web site. Then drag n drop the Store Locator widget from the OCA/Geopspatial section.
|
||||
|
||||
.. figure:: ./static/description/snippet.png
|
||||
|
||||
You can the configure the maximum number of results you want to display before to force your user to filter results.
|
||||
|
||||
.. figure:: ./static/description/snippet_configuration.png
|
||||
|
||||
Then go to 'Contact' app and add some store type address to your contacts and add them some tags.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
* Stéphane Brunner <stephane.brunner@camptocamp.com>
|
||||
* Hadrien Huvelle <hadrien.huvelle@camptocamp.com>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
This module extends the ``website_geoengine`` odoo module, to add
|
||||
a map snippet view for the website.
|
||||
By default the map features are filtered to only display contact of type `store`.
|
||||
|
|
@ -0,0 +1 @@
|
|||
.. figure:: ./static/description/screencast.gif
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
|
|
@ -0,0 +1,448 @@
|
|||
<!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>Geospatial Website store locator</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="geospatial-website-store-locator">
|
||||
<h1 class="title">Geospatial Website store locator</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! source digest: sha256:fe322224dbdd376eea03ba9aa37eaf3c4bc975d36a999b33a2f799caf36e441f
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.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/website_geoengine_store_locator"><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-website_geoengine_store_locator"><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&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 the <tt class="docutils literal">website_geoengine</tt> odoo module, to add
|
||||
a map snippet view for the website.
|
||||
By default the map features are filtered to only display contact of type <cite>store</cite>.</p>
|
||||
<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="#usage" id="toc-entry-2">Usage</a></li>
|
||||
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="configuration">
|
||||
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
|
||||
<p>You should configure first a web site. Then drag n drop the Store Locator widget from the OCA/Geopspatial section.</p>
|
||||
<div class="figure">
|
||||
<img alt="https://raw.githubusercontent.com/OCA/geospatial/16.0/website_geoengine_store_locator/static/description/snippet.png" src="https://raw.githubusercontent.com/OCA/geospatial/16.0/website_geoengine_store_locator/static/description/snippet.png" />
|
||||
</div>
|
||||
<p>You can the configure the maximum number of results you want to display before to force your user to filter results.</p>
|
||||
<div class="figure">
|
||||
<img alt="https://raw.githubusercontent.com/OCA/geospatial/16.0/website_geoengine_store_locator/static/description/snippet_configuration.png" src="https://raw.githubusercontent.com/OCA/geospatial/16.0/website_geoengine_store_locator/static/description/snippet_configuration.png" />
|
||||
</div>
|
||||
<p>Then go to ‘Contact’ app and add some store type address to your contacts and add them some tags.</p>
|
||||
</div>
|
||||
<div class="section" id="usage">
|
||||
<h1><a class="toc-backref" href="#toc-entry-2">Usage</a></h1>
|
||||
<div class="figure">
|
||||
<img alt="https://raw.githubusercontent.com/OCA/geospatial/16.0/website_geoengine_store_locator/static/description/screencast.gif" src="https://raw.githubusercontent.com/OCA/geospatial/16.0/website_geoengine_store_locator/static/description/screencast.gif" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#toc-entry-3">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:%20website_geoengine_store_locator%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-4">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Camptocamp</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Stéphane Brunner <<a class="reference external" href="mailto:stephane.brunner@camptocamp.com">stephane.brunner@camptocamp.com</a>></li>
|
||||
<li>Hadrien Huvelle <<a class="reference external" href="mailto:hadrien.huvelle@camptocamp.com">hadrien.huvelle@camptocamp.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#toc-entry-7">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/Wouitmil"><img alt="Wouitmil" src="https://github.com/Wouitmil.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/website_geoengine_store_locator">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: 3.3 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.6 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 671 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 112 KiB |
|
|
@ -0,0 +1,10 @@
|
|||
/package-lock.json
|
||||
/node_modules/*
|
||||
!/node_modules/ol/
|
||||
/node_modules/ol/*
|
||||
!/node_modules/ol/ol.css
|
||||
!/node_modules/ol/dist/
|
||||
!/node_modules/jquery-flexdatalist/
|
||||
/node_modules/jquery-flexdatalist/*
|
||||
!/node_modules/jquery-flexdatalist/jquery.flexdatalist.css
|
||||
!/node_modules/jquery-flexdatalist/jquery.flexdatalist.js
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
* jQuery Flexdatalist basic stylesheet.
|
||||
*
|
||||
* Version:
|
||||
* 2.3.1
|
||||
*
|
||||
* Github:
|
||||
* https://github.com/sergiodlopes/jquery-flexdatalist/
|
||||
*
|
||||
*/
|
||||
.flexdatalist-results {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 1px solid #444;
|
||||
border-top: none;
|
||||
background: #fff;
|
||||
z-index: 100000;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
box-shadow: 0 4px 5px rgba(0, 0, 0, 0.15);
|
||||
color: #333;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.flexdatalist-results li {
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding: 8px 15px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.flexdatalist-results li span.highlight {
|
||||
font-weight: 700;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.flexdatalist-results li.active {
|
||||
background: #2B82C9;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
.flexdatalist-results li.no-results {
|
||||
font-style: italic;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grouped items
|
||||
*/
|
||||
.flexdatalist-results li.group {
|
||||
background: #F3F3F4;
|
||||
color: #666;
|
||||
padding: 8px 8px;
|
||||
}
|
||||
.flexdatalist-results li .group-name {
|
||||
font-weight: 700;
|
||||
}
|
||||
.flexdatalist-results li .group-item-count {
|
||||
font-size: 85%;
|
||||
color: #777;
|
||||
display: inline-block;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiple items
|
||||
*/
|
||||
.flexdatalist-multiple:before {
|
||||
content: '';
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
.flexdatalist-multiple {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
text-align: left;
|
||||
cursor: text;
|
||||
}
|
||||
.flexdatalist-multiple.disabled {
|
||||
background-color: #eee;
|
||||
cursor: default;
|
||||
}
|
||||
.flexdatalist-multiple:after {
|
||||
content: '';
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
.flexdatalist-multiple li {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
margin: 5px;
|
||||
}
|
||||
.flexdatalist-multiple li.input-container,
|
||||
.flexdatalist-multiple li.input-container input {
|
||||
border: none;
|
||||
height: auto;
|
||||
padding: 0 0 0 4px;
|
||||
line-height: 24px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.flexdatalist-multiple li.value {
|
||||
padding: 2px 25px 2px 7px;
|
||||
background: #efefef;
|
||||
border-radius: 3px;
|
||||
color: #444;
|
||||
line-height: 20px;
|
||||
float: left;
|
||||
}
|
||||
.flexdatalist-multiple li.toggle {
|
||||
cursor: pointer;
|
||||
transition: opacity ease-in-out 300ms;
|
||||
}
|
||||
.flexdatalist-multiple li.toggle.disabled {
|
||||
text-decoration: line-through;
|
||||
opacity: 0.80;
|
||||
}
|
||||
|
||||
.flexdatalist-multiple li.value span.fdl-remove {
|
||||
font-weight: 700;
|
||||
padding: 2px 5px;
|
||||
font-size: 20px;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
opacity: 0.70;
|
||||
}
|
||||
.flexdatalist-multiple li.value span.fdl-remove:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
4
odoo-bringout-oca-geospatial-website_geoengine_store_locator/website_geoengine_store_locator/static/lib/node_modules/ol/dist/ol.js
generated
vendored
Normal file
4
odoo-bringout-oca-geospatial-website_geoengine_store_locator/website_geoengine_store_locator/static/lib/node_modules/ol/dist/ol.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
350
odoo-bringout-oca-geospatial-website_geoengine_store_locator/website_geoengine_store_locator/static/lib/node_modules/ol/ol.css
generated
vendored
Normal file
350
odoo-bringout-oca-geospatial-website_geoengine_store_locator/website_geoengine_store_locator/static/lib/node_modules/ol/ol.css
generated
vendored
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
:root,
|
||||
:host {
|
||||
--ol-background-color: white;
|
||||
--ol-accent-background-color: #F5F5F5;
|
||||
--ol-subtle-background-color: rgba(128, 128, 128, 0.25);
|
||||
--ol-partial-background-color: rgba(255, 255, 255, 0.75);
|
||||
--ol-foreground-color: #333333;
|
||||
--ol-subtle-foreground-color: #666666;
|
||||
--ol-brand-color: #00AAFF;
|
||||
}
|
||||
|
||||
.ol-box {
|
||||
box-sizing: border-box;
|
||||
border-radius: 2px;
|
||||
border: 1.5px solid var(--ol-background-color);
|
||||
background-color: var(--ol-partial-background-color);
|
||||
}
|
||||
|
||||
.ol-mouse-position {
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ol-scale-line {
|
||||
background: var(--ol-partial-background-color);
|
||||
border-radius: 4px;
|
||||
bottom: 8px;
|
||||
left: 8px;
|
||||
padding: 2px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ol-scale-line-inner {
|
||||
border: 1px solid var(--ol-subtle-foreground-color);
|
||||
border-top: none;
|
||||
color: var(--ol-foreground-color);
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
margin: 1px;
|
||||
will-change: contents, width;
|
||||
transition: all 0.25s;
|
||||
}
|
||||
|
||||
.ol-scale-bar {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
left: 8px;
|
||||
}
|
||||
|
||||
.ol-scale-bar-inner {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ol-scale-step-marker {
|
||||
width: 1px;
|
||||
height: 15px;
|
||||
background-color: var(--ol-foreground-color);
|
||||
float: right;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.ol-scale-step-text {
|
||||
position: absolute;
|
||||
bottom: -5px;
|
||||
font-size: 10px;
|
||||
z-index: 11;
|
||||
color: var(--ol-foreground-color);
|
||||
text-shadow: -1.5px 0 var(--ol-partial-background-color), 0 1.5px var(--ol-partial-background-color), 1.5px 0 var(--ol-partial-background-color), 0 -1.5px var(--ol-partial-background-color);
|
||||
}
|
||||
|
||||
.ol-scale-text {
|
||||
position: absolute;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
bottom: 25px;
|
||||
color: var(--ol-foreground-color);
|
||||
text-shadow: -1.5px 0 var(--ol-partial-background-color), 0 1.5px var(--ol-partial-background-color), 1.5px 0 var(--ol-partial-background-color), 0 -1.5px var(--ol-partial-background-color);
|
||||
}
|
||||
|
||||
.ol-scale-singlebar {
|
||||
position: relative;
|
||||
height: 10px;
|
||||
z-index: 9;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid var(--ol-foreground-color);
|
||||
}
|
||||
|
||||
.ol-scale-singlebar-even {
|
||||
background-color: var(--ol-subtle-foreground-color);
|
||||
}
|
||||
|
||||
.ol-scale-singlebar-odd {
|
||||
background-color: var(--ol-background-color);
|
||||
}
|
||||
|
||||
.ol-unsupported {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ol-viewport,
|
||||
.ol-unselectable {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.ol-viewport canvas {
|
||||
all: unset;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ol-viewport {
|
||||
touch-action: pan-x pan-y;
|
||||
}
|
||||
|
||||
.ol-selectable {
|
||||
-webkit-touch-callout: default;
|
||||
-webkit-user-select: text;
|
||||
-moz-user-select: text;
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
.ol-grabbing {
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.ol-grab {
|
||||
cursor: move;
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.ol-control {
|
||||
position: absolute;
|
||||
background-color: var(--ol-subtle-background-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.ol-zoom {
|
||||
top: .5em;
|
||||
left: .5em;
|
||||
}
|
||||
|
||||
.ol-rotate {
|
||||
top: .5em;
|
||||
right: .5em;
|
||||
transition: opacity .25s linear, visibility 0s linear;
|
||||
}
|
||||
|
||||
.ol-rotate.ol-hidden {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity .25s linear, visibility 0s linear .25s;
|
||||
}
|
||||
|
||||
.ol-zoom-extent {
|
||||
top: 4.643em;
|
||||
left: .5em;
|
||||
}
|
||||
|
||||
.ol-full-screen {
|
||||
right: .5em;
|
||||
top: .5em;
|
||||
}
|
||||
|
||||
.ol-control button {
|
||||
display: block;
|
||||
margin: 1px;
|
||||
padding: 0;
|
||||
color: var(--ol-subtle-foreground-color);
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
font-size: inherit;
|
||||
text-align: center;
|
||||
height: 1.375em;
|
||||
width: 1.375em;
|
||||
line-height: .4em;
|
||||
background-color: var(--ol-background-color);
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.ol-control button::-moz-focus-inner {
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ol-zoom-extent button {
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
.ol-compass {
|
||||
display: block;
|
||||
font-weight: normal;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.ol-touch .ol-control button {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.ol-touch .ol-zoom-extent {
|
||||
top: 5.5em;
|
||||
}
|
||||
|
||||
.ol-control button:hover,
|
||||
.ol-control button:focus {
|
||||
text-decoration: none;
|
||||
outline: 1px solid var(--ol-subtle-foreground-color);
|
||||
color: var(--ol-foreground-color);
|
||||
}
|
||||
|
||||
.ol-zoom .ol-zoom-in {
|
||||
border-radius: 2px 2px 0 0;
|
||||
}
|
||||
|
||||
.ol-zoom .ol-zoom-out {
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
|
||||
.ol-attribution {
|
||||
text-align: right;
|
||||
bottom: .5em;
|
||||
right: .5em;
|
||||
max-width: calc(100% - 1.3em);
|
||||
display: flex;
|
||||
flex-flow: row-reverse;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ol-attribution a {
|
||||
color: var(--ol-subtle-foreground-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.ol-attribution ul {
|
||||
margin: 0;
|
||||
padding: 1px .5em;
|
||||
color: var(--ol-foreground-color);
|
||||
text-shadow: 0 0 2px var(--ol-background-color);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ol-attribution li {
|
||||
display: inline;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.ol-attribution li:not(:last-child):after {
|
||||
content: " ";
|
||||
}
|
||||
|
||||
.ol-attribution img {
|
||||
max-height: 2em;
|
||||
max-width: inherit;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.ol-attribution button {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ol-attribution.ol-collapsed ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ol-attribution:not(.ol-collapsed) {
|
||||
background: var(--ol-partial-background-color);
|
||||
}
|
||||
|
||||
.ol-attribution.ol-uncollapsible {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
border-radius: 4px 0 0;
|
||||
}
|
||||
|
||||
.ol-attribution.ol-uncollapsible img {
|
||||
margin-top: -.2em;
|
||||
max-height: 1.6em;
|
||||
}
|
||||
|
||||
.ol-attribution.ol-uncollapsible button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ol-zoomslider {
|
||||
top: 4.5em;
|
||||
left: .5em;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.ol-zoomslider button {
|
||||
position: relative;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.ol-touch .ol-zoomslider {
|
||||
top: 5.5em;
|
||||
}
|
||||
|
||||
.ol-overviewmap {
|
||||
left: 0.5em;
|
||||
bottom: 0.5em;
|
||||
}
|
||||
|
||||
.ol-overviewmap.ol-uncollapsible {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-radius: 0 4px 0 0;
|
||||
}
|
||||
|
||||
.ol-overviewmap .ol-overviewmap-map,
|
||||
.ol-overviewmap button {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ol-overviewmap .ol-overviewmap-map {
|
||||
border: 1px solid var(--ol-subtle-foreground-color);
|
||||
height: 150px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.ol-overviewmap:not(.ol-collapsed) button {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.ol-overviewmap.ol-collapsed .ol-overviewmap-map,
|
||||
.ol-overviewmap.ol-uncollapsible button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ol-overviewmap:not(.ol-collapsed) {
|
||||
background: var(--ol-subtle-background-color);
|
||||
}
|
||||
|
||||
.ol-overviewmap-box {
|
||||
border: 1.5px dotted var(--ol-subtle-foreground-color);
|
||||
}
|
||||
|
||||
.ol-overviewmap .ol-overviewmap-box:hover {
|
||||
cursor: move;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"ol": "8.2.0",
|
||||
"jquery-flexdatalist": "2.3.0"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -0,0 +1,33 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
/**
|
||||
* Copyright 2011-2024 Camptocamp SA
|
||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
*/
|
||||
|
||||
import OpenLayerMap from "./map.esm";
|
||||
import publicWidget from "web.public.widget";
|
||||
|
||||
publicWidget.registry.OpenLayerStoreLocator = publicWidget.Widget.extend({
|
||||
selector: ".s_openlayer_store_locator",
|
||||
cssLibs: [
|
||||
"/website_geoengine_store_locator/static/styles.css",
|
||||
"/website_geoengine_store_locator/static/lib/node_modules/ol/ol.css",
|
||||
"/website_geoengine_store_locator/static/lib/node_modules/jquery-flexdatalist/jquery.flexdatalist.css",
|
||||
],
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start() {
|
||||
console.log("start");
|
||||
if (!this.el.querySelector(".ol-viewport")) {
|
||||
const dataset = this.el.dataset;
|
||||
this.element = this.el;
|
||||
this.map = new OpenLayerMap(this.element, dataset.mapType);
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
|
||||
export default publicWidget.registry.OpenLayerStoreLocator;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/** @odoo-module alias=website_geoengine_store_locator.openlayer_map */
|
||||
|
||||
/**
|
||||
* Copyright 2011-2024 Camptocamp SA
|
||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
*/
|
||||
|
||||
import Popover from "./popover.esm";
|
||||
import Search from "./search.esm";
|
||||
|
||||
/**
|
||||
* The base class that manage all the map
|
||||
*/
|
||||
class OpenLayerMap {
|
||||
constructor(element, mapType = "mapnik") {
|
||||
const dataset = element.dataset;
|
||||
const storesSource = new ol.source.Vector();
|
||||
const stores = new ol.layer.Vector({
|
||||
source: storesSource,
|
||||
});
|
||||
const mapElement = element.querySelector(".map");
|
||||
const map = new ol.Map({
|
||||
target: mapElement,
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.OSM({
|
||||
url: {
|
||||
mapnik: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
cyclemap:
|
||||
"https://tile.thunderforest.com/cycle/{z}/{x}/{y}@2x.png?apikey=...",
|
||||
cyclosm:
|
||||
"https://{a-c}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png",
|
||||
mobility:
|
||||
"https://tile.thunderforest.com/transport/{z}/{x}/{y}@2x.png?apikey=...",
|
||||
topo: "https://tile.tracestrack.com/topo__/{z}/{x}/{y}.png?key=...",
|
||||
hot: "https://tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",
|
||||
}[mapType],
|
||||
}),
|
||||
}),
|
||||
stores,
|
||||
],
|
||||
view: new ol.View({
|
||||
projection: "EPSG:3857",
|
||||
center: ol.proj.fromLonLat([6, 46]),
|
||||
zoom: 8,
|
||||
minResolution: 0.299,
|
||||
}),
|
||||
});
|
||||
|
||||
if (mapElement) {
|
||||
new Popover(element.querySelector("#popup"), map);
|
||||
new Search(
|
||||
element.querySelector("#search"),
|
||||
map,
|
||||
mapElement,
|
||||
stores,
|
||||
dataset.maxResults,
|
||||
dataset.mapZoom
|
||||
);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
export default OpenLayerMap;
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/** @odoo-module */
|
||||
|
||||
/**
|
||||
* Copyright 2011-2024 Camptocamp SA
|
||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
*/
|
||||
|
||||
class Popover {
|
||||
constructor(element, map) {
|
||||
/**
|
||||
* The popover
|
||||
* @param {jQuery} popover
|
||||
*/
|
||||
this.popover = undefined;
|
||||
/**
|
||||
* The map
|
||||
* @param {ol.Map} map
|
||||
*/
|
||||
this.map = map;
|
||||
/**
|
||||
* The base element
|
||||
* @param {HTMLElement} element
|
||||
*/
|
||||
this.element = element;
|
||||
/**
|
||||
* The jQuery base element
|
||||
* @type {jQuery}
|
||||
*/
|
||||
this.jqueryElement = $(element);
|
||||
/**
|
||||
* The popup overlay
|
||||
* @param {ol.Overlay} popup
|
||||
*/
|
||||
this.popup = new ol.Overlay({
|
||||
element: this.element,
|
||||
positioning: "bottom-center",
|
||||
stopEvent: false,
|
||||
});
|
||||
map.addOverlay(this.popup);
|
||||
map.on("click", this.mapOnClick.bind(this));
|
||||
map.on("pointermove", this.mapOnPointerMove.bind(this));
|
||||
map.getView().on("change:center", this.mapOnMove.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose the popover
|
||||
*/
|
||||
disposePopover() {
|
||||
console.log("disposePopover");
|
||||
if (this.popover) {
|
||||
this.popover.popover("dispose");
|
||||
this.popover = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
mapOnMove() {
|
||||
if (!this.feature) {
|
||||
return;
|
||||
}
|
||||
$(this.element).popover("show");
|
||||
}
|
||||
|
||||
/**
|
||||
* The function called on map click event
|
||||
* @param {ol.MapBrowserEvent} event
|
||||
*/
|
||||
mapOnClick(event) {
|
||||
this.feature = this.map.forEachFeatureAtPixel(event.pixel, function (feature) {
|
||||
return feature;
|
||||
});
|
||||
|
||||
this.disposePopover();
|
||||
if (!this.feature) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.popup.setPosition(this.feature.getGeometry().getFirstCoordinate());
|
||||
if (!this.popover) {
|
||||
this.popover = $(this.element).popover({
|
||||
placement: "top",
|
||||
html: true,
|
||||
trigger: "focus",
|
||||
content: `
|
||||
<b>${this.feature.get("name")}</b><br/>
|
||||
${this.feature.get("street")}<br/>
|
||||
${this.feature.get("street2")}<br/>
|
||||
${this.feature.get("zip")} ${this.feature.get("city")}<br/>
|
||||
${this.feature.get("tags")}<br/>
|
||||
${this.feature.get("opening_hours")}`,
|
||||
});
|
||||
}
|
||||
this.popover.popover("show");
|
||||
}
|
||||
|
||||
/**
|
||||
* The function called on map pointer move event
|
||||
* @param {ol.MapBrowserEvent} e
|
||||
*/
|
||||
mapOnPointerMove(e) {
|
||||
const pixel = this.map.getEventPixel(e.originalEvent);
|
||||
const hit = this.map.hasFeatureAtPixel(pixel);
|
||||
this.map.getTarget().style.cursor = hit ? "pointer" : "";
|
||||
}
|
||||
}
|
||||
|
||||
export default Popover;
|
||||
|
|
@ -0,0 +1,407 @@
|
|||
/** @odoo-module **/
|
||||
|
||||
/**
|
||||
* Copyright 2011-2024 Camptocamp SA
|
||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
*/
|
||||
|
||||
import session from "web.session";
|
||||
|
||||
/**
|
||||
* Create a standard symbol for a POI
|
||||
* @param {Number} height the height of the circle center
|
||||
* @param {Number} radius the radius of the top circle
|
||||
* @param {String} fillColor the fill color of the symbol
|
||||
* @param {Number} strokeWidth the stroke width of the symbol
|
||||
* @param {String} strokeColor the stroke color of the symbol
|
||||
* @param {Number} centerRadius the radius of the center point
|
||||
* @param {String} centerFillColor the fill color of the center point
|
||||
* @param {Number} centerStrokeWidth the stroke width of the center point
|
||||
* @param {String} centerStrokeColor the stroke color of the center point
|
||||
* @returns {Object} the canvas
|
||||
*/
|
||||
function buildCanvas(
|
||||
height,
|
||||
radius,
|
||||
fillColor,
|
||||
strokeWidth,
|
||||
strokeColor,
|
||||
centerRadius,
|
||||
centerFillColor,
|
||||
centerStrokeWidth,
|
||||
centerStrokeColor
|
||||
) {
|
||||
const negateHeight = height < 0;
|
||||
height = Math.abs(height);
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = Math.ceil(radius * 2 + strokeWidth);
|
||||
canvas.height = Math.ceil(
|
||||
height < radius ? radius * 2 + strokeWidth : radius + height + strokeWidth
|
||||
);
|
||||
const context = canvas.getContext("2d");
|
||||
if (negateHeight) {
|
||||
context.setTransform(1, 0, 0, -1, 0, canvas.height);
|
||||
}
|
||||
|
||||
const alpha = radius < height ? Math.acos(radius / height) : 0;
|
||||
const circleCenter = [
|
||||
canvas.width / 2,
|
||||
alpha === 0 ? canvas.width / 2 : radius + strokeWidth / 2,
|
||||
];
|
||||
const linesStart = [canvas.width / 2, radius + height + strokeWidth / 2];
|
||||
const linesWeight = Math.sin(alpha) * radius;
|
||||
const linesHeight = height - Math.cos(alpha) * radius;
|
||||
const line1End = [canvas.width / 2 - linesWeight, linesStart[1] - linesHeight];
|
||||
const line2End = [canvas.width / 2 + linesWeight, linesStart[1] - linesHeight];
|
||||
|
||||
context.fillStyle = fillColor;
|
||||
context.strokeStyle = strokeColor;
|
||||
context.lineWidth = strokeWidth;
|
||||
context.lineJoin = "round";
|
||||
|
||||
context.beginPath();
|
||||
if (alpha === 0) {
|
||||
context.moveTo(circleCenter[0] + radius, circleCenter[1]);
|
||||
context.arc(circleCenter[0], circleCenter[1], radius, 0, Math.PI * 2);
|
||||
} else {
|
||||
context.moveTo(line2End[0], line2End[1]);
|
||||
context.lineTo(linesStart[0], linesStart[1]);
|
||||
context.lineTo(line1End[0], line1End[1]);
|
||||
context.arc(
|
||||
circleCenter[0],
|
||||
circleCenter[1],
|
||||
radius,
|
||||
Math.PI / 2 + alpha,
|
||||
Math.PI / 2 - alpha
|
||||
);
|
||||
context.lineTo(line2End[0], line2End[1]);
|
||||
}
|
||||
context.stroke();
|
||||
context.moveTo(circleCenter[0] + centerRadius, circleCenter[1]);
|
||||
context.arc(circleCenter[0], circleCenter[1], centerRadius, 0, Math.PI * 2, true);
|
||||
context.closePath();
|
||||
context.fill();
|
||||
|
||||
context.fillStyle = centerFillColor;
|
||||
context.strokeStyle = centerStrokeColor;
|
||||
context.lineWidth = centerStrokeWidth;
|
||||
context.beginPath();
|
||||
context.arc(circleCenter[0], circleCenter[1], centerRadius, 0, Math.PI * 2);
|
||||
context.closePath();
|
||||
context.stroke();
|
||||
context.fill("evenodd");
|
||||
return canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to create an icon with a hit detection image
|
||||
*/
|
||||
class StyleIconHit extends ol.style.Icon {
|
||||
setHitDetectionImage(canvas) {
|
||||
this.canvasHit = canvas;
|
||||
}
|
||||
getHitDetectionImage() {
|
||||
return this.canvasHit;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create a standard symbol for a POI
|
||||
* @param {Number} height the height of the circle center
|
||||
* @param {Number} radius the radius of the top circle
|
||||
* @param {String} fillColor the fill color of the symbol
|
||||
* @param {Number} strokeWidth the stroke width of the symbol
|
||||
* @param {String} strokeColor the stroke color of the symbol
|
||||
* @param {Number} centerRadius the radius of the center point
|
||||
* @param {String} centerFillColor the fill color of the center point
|
||||
* @param {Number} centerStrokeWidth the stroke width of the center point
|
||||
* @param {String} centerStrokeColor the stroke color of the center point
|
||||
* @returns {Object} the icon
|
||||
*/
|
||||
function buildIcon(
|
||||
height,
|
||||
radius,
|
||||
fillColor,
|
||||
strokeWidth,
|
||||
strokeColor,
|
||||
centerRadius,
|
||||
centerFillColor,
|
||||
centerStrokeWidth,
|
||||
centerStrokeColor
|
||||
) {
|
||||
const canvas = buildCanvas(
|
||||
height,
|
||||
radius,
|
||||
fillColor,
|
||||
strokeWidth,
|
||||
strokeColor,
|
||||
centerRadius,
|
||||
centerFillColor,
|
||||
centerStrokeWidth,
|
||||
centerStrokeColor
|
||||
);
|
||||
const negateHeight = height < 0;
|
||||
|
||||
const icon =
|
||||
radius >= Math.abs(height)
|
||||
? new StyleIconHit({
|
||||
img: canvas,
|
||||
anchor: [0.5, 0.5 + height / radius / 2],
|
||||
})
|
||||
: new StyleIconHit({
|
||||
img: canvas,
|
||||
anchor: [0.5, negateHeight ? 0 : 1],
|
||||
});
|
||||
|
||||
icon.setHitDetectionImage(
|
||||
buildCanvas(
|
||||
height,
|
||||
radius,
|
||||
fillColor,
|
||||
strokeWidth,
|
||||
strokeColor,
|
||||
0,
|
||||
centerFillColor,
|
||||
centerStrokeWidth,
|
||||
centerStrokeColor
|
||||
)
|
||||
);
|
||||
return icon;
|
||||
}
|
||||
|
||||
class Search {
|
||||
constructor(element, map, mapElement, stores, maxResults = 200, mapZoom = -1) {
|
||||
/**
|
||||
* The search input element
|
||||
* @type {HTMLInputElement}
|
||||
*/
|
||||
this.element = element;
|
||||
/**
|
||||
* The search input JQuery element
|
||||
* @type {JQuery<HTMLElement>}
|
||||
*/
|
||||
this.jquery_element = $(element);
|
||||
this.jquery_element.val("");
|
||||
|
||||
/**
|
||||
* The map
|
||||
* @type {ol.Map}
|
||||
*/
|
||||
this.map = map;
|
||||
/**
|
||||
* The stores layer
|
||||
* @type {ol.layer.Vector}
|
||||
*/
|
||||
this.stores = stores;
|
||||
/**
|
||||
* The last search text
|
||||
* @type {string}
|
||||
*/
|
||||
this.last_search_text = "";
|
||||
|
||||
/**
|
||||
* The search input element
|
||||
* @type {HTMLInputElement}
|
||||
*/
|
||||
this.mapElement = mapElement;
|
||||
/**
|
||||
* The maximum number of results
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxResults = maxResults;
|
||||
/**
|
||||
* The zoom level of the map
|
||||
* @type {number}
|
||||
*/
|
||||
this.mapZoom = mapZoom;
|
||||
/**
|
||||
* The message element
|
||||
* @type {JQuery<HTMLElement>}
|
||||
*/
|
||||
this.message = null;
|
||||
|
||||
this.stores.setStyle(
|
||||
new ol.style.Style({
|
||||
image: buildIcon(
|
||||
20,
|
||||
10,
|
||||
"rgba(44, 131, 151, 0.8)",
|
||||
2,
|
||||
"rgb(0, 0, 0)",
|
||||
4,
|
||||
"rgba(0, 0, 0, 0)",
|
||||
2,
|
||||
"rgb(0, 0, 0)"
|
||||
),
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* The format to read the features
|
||||
* @type {ol.format.GeoJSON}
|
||||
*/
|
||||
this.format = new ol.format.GeoJSON({
|
||||
dataProjection: "EPSG:4326",
|
||||
featureProjection: "EPSG:3857",
|
||||
});
|
||||
|
||||
/**
|
||||
* The language of the user
|
||||
* @type {string}
|
||||
*/
|
||||
this.lang = (document.documentElement.getAttribute("lang") || "en_US").replace(
|
||||
"-",
|
||||
"_"
|
||||
);
|
||||
|
||||
this.jquery_element.flexdatalist({
|
||||
minLength: 3,
|
||||
multiple: true,
|
||||
focusFirstResult: true,
|
||||
maxShownResults: 10,
|
||||
searchIn: ["value"],
|
||||
// Combo box
|
||||
visibleProperties: ["text"],
|
||||
// Tag list in field
|
||||
textProperty: "text",
|
||||
// The managed value
|
||||
valueProperty: "text",
|
||||
searchContain: true,
|
||||
cache: false,
|
||||
});
|
||||
|
||||
/**
|
||||
* The input element of the flexdatalist
|
||||
* @type {HTMLInputElement}
|
||||
*/
|
||||
this.jquery_input_element = element.querySelector("ul input");
|
||||
this.jquery_element.on("before:flexdatalist.search", this.loadDatas.bind(this));
|
||||
this.jquery_element.on("change:flexdatalist", () => {
|
||||
const value = this.jquery_element.flexdatalist("value");
|
||||
if (value.length === 0) {
|
||||
// Initial state
|
||||
this.loadPartners([], true);
|
||||
return;
|
||||
}
|
||||
const arg = [];
|
||||
for (const item of value) {
|
||||
const value_split = item.split(":");
|
||||
if (value_split.length === 2) {
|
||||
arg.push({field: value_split[0], value: value_split[1].trim()});
|
||||
}
|
||||
}
|
||||
|
||||
this.loadPartners(arg);
|
||||
});
|
||||
|
||||
this.loadPartners([], true);
|
||||
}
|
||||
|
||||
loadPartners(tags, firstTime = false) {
|
||||
if (this.message !== null) {
|
||||
this.mapElement.removeChild(this.message[0]);
|
||||
this.message = null;
|
||||
}
|
||||
|
||||
const args = {
|
||||
tags: tags,
|
||||
lang: this.lang,
|
||||
maxResults: this.maxResults,
|
||||
};
|
||||
|
||||
session.rpc("/website-geoengine/partners", args).then(
|
||||
(result) => {
|
||||
const storesSource = this.stores.getSource();
|
||||
storesSource.clear();
|
||||
if ("error" in result) {
|
||||
this.message = $("<div>", {});
|
||||
this.message.addClass("message");
|
||||
this.message.click(() => {
|
||||
this.mapElement.removeChild(this.message[0]);
|
||||
this.message = null;
|
||||
});
|
||||
if (firstTime) {
|
||||
this.message.text("Use the search field to find a store");
|
||||
} else {
|
||||
this.message.text(
|
||||
"Too many results, please refine your search"
|
||||
);
|
||||
}
|
||||
$(this.mapElement).append(this.message);
|
||||
this.map.getView().setZoom(this.mapZoom);
|
||||
return;
|
||||
}
|
||||
for (const feature of result) {
|
||||
storesSource.addFeature(this.format.readFeature(feature));
|
||||
}
|
||||
if (storesSource.getFeatures().length === 0) {
|
||||
return;
|
||||
}
|
||||
const extent = storesSource.getExtent();
|
||||
const addWidth = (extent[2] - extent[0]) / 10;
|
||||
const addHeight = (extent[3] - extent[1]) / 10;
|
||||
if (addWidth === 0 && addHeight === 0) {
|
||||
this.map.getView().setCenter([extent[0], extent[1]]);
|
||||
} else {
|
||||
this.map
|
||||
.getView()
|
||||
.fit([
|
||||
extent[0] - addWidth,
|
||||
extent[1] - addHeight,
|
||||
extent[2] + addWidth,
|
||||
extent[3] + addHeight,
|
||||
]);
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.log(error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
loadDatas(event, text) {
|
||||
if (text === this.last_search_text) {
|
||||
return;
|
||||
}
|
||||
this.last_search_text = text;
|
||||
|
||||
if (this.message !== null) {
|
||||
this.mapElement.removeChild(this.message[0]);
|
||||
this.message = null;
|
||||
}
|
||||
|
||||
this.jquery_element.flexdatalist("data", []);
|
||||
this.jquery_element.flexdatalist("noResultsText", "Loading...");
|
||||
|
||||
const args = {
|
||||
tags: text,
|
||||
lang: this.lang,
|
||||
};
|
||||
session.rpc("/website-geoengine/tags", args).then(
|
||||
(result) => {
|
||||
const data = [];
|
||||
for (const item of result) {
|
||||
data.push({
|
||||
value: item[1],
|
||||
text: `${item[0]}: ${item[1]}`,
|
||||
});
|
||||
}
|
||||
this.jquery_element.flexdatalist("data", data);
|
||||
$(this.element.parentElement.querySelector("ul input")).keyup();
|
||||
this.jquery_element.flexdatalist(
|
||||
"noResultsText",
|
||||
'No results found for "{keyword}"'
|
||||
);
|
||||
},
|
||||
(error) => {
|
||||
console.error(error);
|
||||
this.jquery_element.flexdatalist(
|
||||
"noResultsText",
|
||||
"Error while loading data"
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Search;
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
/** @odoo-module **/
|
||||
import options from "web_editor.snippets.options";
|
||||
|
||||
/**
|
||||
* Copyright 2011-2024 Camptocamp SA
|
||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
|
||||
*/
|
||||
|
||||
options.registry.OpenLayerStoreLocator = options.Class.extend({
|
||||
jsLibs: [
|
||||
"/web/static/lib/Chart/Chart.js",
|
||||
"/website_geoengine_store_locator/static/lib/node_modules/ol/dist/ol.js",
|
||||
"/website_geoengine_store_locator/static/lib/node_modules/jquery-flexdatalist/jquery.flexdatalist.js",
|
||||
],
|
||||
cssLibs: [
|
||||
"/website_geoengine_store_locator/static/styles.css",
|
||||
"/website_geoengine_store_locator/static/lib/node_modules/ol/ol.css",
|
||||
"/website_geoengine_store_locator/static/lib/node_modules/jquery-flexdatalist/jquery.flexdatalist.css",
|
||||
],
|
||||
|
||||
init() {
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
async onBuilt() {
|
||||
this._super.apply(this, arguments);
|
||||
this.element = this.$target[0];
|
||||
this.mapType = this.element.dataset.mapType;
|
||||
|
||||
const storesSource = new ol.source.Vector();
|
||||
const stores = new ol.layer.Vector({
|
||||
source: storesSource,
|
||||
});
|
||||
this.mapElement = this.element.querySelector(".map");
|
||||
new ol.Map({
|
||||
target: this.mapElement,
|
||||
layers: [
|
||||
new ol.layer.Tile({
|
||||
source: new ol.source.OSM({
|
||||
url: {
|
||||
mapnik: "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
|
||||
cyclemap:
|
||||
"https://tile.thunderforest.com/cycle/{z}/{x}/{y}@2x.png?apikey=...",
|
||||
cyclosm:
|
||||
"https://{a-c}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png",
|
||||
mobility:
|
||||
"https://tile.thunderforest.com/transport/{z}/{x}/{y}@2x.png?apikey=...",
|
||||
topo: "https://tile.tracestrack.com/topo__/{z}/{x}/{y}.png?key=...",
|
||||
hot: "https://tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",
|
||||
}[this.mapType],
|
||||
}),
|
||||
}),
|
||||
stores,
|
||||
],
|
||||
view: new ol.View({
|
||||
projection: "EPSG:3857",
|
||||
center: ol.proj.fromLonLat([6, 46]),
|
||||
zoom: 8,
|
||||
}),
|
||||
});
|
||||
},
|
||||
|
||||
async selectDataAttribute(previewMode, widgetValue, params) {
|
||||
await this._super(...arguments);
|
||||
if (params.attributeName === "maxResults" && previewMode === false) {
|
||||
return (this.$target.get(0).dataset.maxResults = widgetValue);
|
||||
}
|
||||
if (["mapType", "mapZoom"].includes(params.attributeName)) {
|
||||
console.log("Change in map options not implemented yet");
|
||||
}
|
||||
},
|
||||
|
||||
cleanForSave() {
|
||||
this.mapElement.innerHTML = "";
|
||||
},
|
||||
});
|
||||
|
||||
export default {
|
||||
OpenLayerStoreLocator: options.registry.OpenLayerStoreLocator,
|
||||
};
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
$s-map-desc-bg: map-get($theme-colors, "primary") !default;
|
||||
$s-map-desc-alpha: 0.8 !default;
|
||||
$s-map-desc-hover-bg: map-get($theme-colors, "primary") !default;
|
||||
$s-map-desc-hover-alpha: 0.55 !default;
|
||||
|
||||
.s_openlayer_store_locator {
|
||||
position: relative;
|
||||
min-height: 100px;
|
||||
|
||||
.map_container {
|
||||
@include o-position-absolute(0, 0, 0, 0);
|
||||
|
||||
.map {
|
||||
@include o-position-absolute(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
.description {
|
||||
@include o-position-absolute(auto, 0, 0, 0);
|
||||
z-index: 99;
|
||||
padding: 0 1em;
|
||||
background: rgba($s-map-desc-bg, $s-map-desc-alpha);
|
||||
color: color-contrast(rgba($s-map-desc-bg, $s-map-desc-alpha));
|
||||
transition: background-color 250ms ease;
|
||||
|
||||
font {
|
||||
float: left;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 15px;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
span {
|
||||
float: left;
|
||||
text-transform: none;
|
||||
font-weight: normal;
|
||||
margin-top: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
&:hover .description {
|
||||
background: $s-map-desc-hover-bg;
|
||||
background: rgba($s-map-desc-hover-bg, $s-map-desc-hover-alpha);
|
||||
color: color-contrast(rgba($s-map-desc-hover-bg, $s-map-desc-hover-alpha));
|
||||
}
|
||||
.s_openlayer_store_locator_color_filter {
|
||||
@include o-position-absolute(0, 0, 0, 0);
|
||||
position: absolute !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.editor_enable .s_openlayer_store_locator {
|
||||
// any thing needed while editing widget
|
||||
.description {
|
||||
background: rgba($s-map-desc-bg, $s-map-desc-alpha);
|
||||
color: color-contrast(rgba($s-map-desc-bg, $s-map-desc-alpha));
|
||||
}
|
||||
.s_openlayer_store_locator_color_filter {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
.map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.search {
|
||||
position: absolute;
|
||||
top: 0.5rem;
|
||||
left: 3rem;
|
||||
min-width: 15rem;
|
||||
}
|
||||
.search input {
|
||||
border-color: lightgrey;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.search input:focus {
|
||||
outline: none;
|
||||
}
|
||||
/* Hide the old field */
|
||||
.search > .flexdatalist-alias.search-flexdatalist {
|
||||
visibility: hidden;
|
||||
}
|
||||
.search .value {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
.search .text {
|
||||
background-color: lightgray;
|
||||
border-radius: 5px;
|
||||
border-color: gray;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
padding: 0.2rem 0.4rem;
|
||||
}
|
||||
.message {
|
||||
position: absolute;
|
||||
width: 20%;
|
||||
z-index: 999;
|
||||
top: 1rem;
|
||||
left: 40%;
|
||||
background: white;
|
||||
border: rgb(211, 211, 211) solid 1px;
|
||||
padding: 0.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
|
||||
<template name="OpenLayer Store Locator" id="s_openlayer_store_locator">
|
||||
<section
|
||||
class="s_openlayer_store_locator pb56 pt56"
|
||||
data-vjs="001"
|
||||
data-map-type="mapnik"
|
||||
data-map-zoom="12"
|
||||
data-max-results="200"
|
||||
>
|
||||
<div class="map_container o_not_editable">
|
||||
<div class="map" id="map" />
|
||||
<div class="search">
|
||||
<input
|
||||
type="text"
|
||||
id="search"
|
||||
class="flexdatalist"
|
||||
placeholder="Search store"
|
||||
/>
|
||||
</div>
|
||||
<div id="popup" />
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<!-- Snippet's Options -->
|
||||
<template id="s_openlayer_store_locator_options" inherit_id="website.snippet_options">
|
||||
<xpath expr="//div[@data-js='Box']" position="before">
|
||||
<div data-js="OpenLayerStoreLocator" data-selector=".s_openlayer_store_locator">
|
||||
<we-input
|
||||
class="o_we_large"
|
||||
string="Max number of results"
|
||||
data-select-data-attribute=""
|
||||
data-no-preview="true"
|
||||
data-attribute-name="maxResults"
|
||||
placeholder="200"
|
||||
/>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<template
|
||||
id="website_geoengine_store_locator_snipet"
|
||||
inherit_id="website.snippets"
|
||||
priority="8"
|
||||
>
|
||||
<xpath expr="//div[@id='snippet_structure']" position="before">
|
||||
<div class="o_panel_header">OCA/Geospatial</div>
|
||||
<div class="o_panel_body">
|
||||
<t
|
||||
t-snippet="website_geoengine_store_locator.s_openlayer_store_locator"
|
||||
t-thumbnail="/website_geoengine_store_locator/static/src/img/snippets_thumbs/s_openlayer_store_locator.png"
|
||||
string="Store Locator"
|
||||
>
|
||||
<keywords>map, store</keywords>
|
||||
</t>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
||||
Loading…
Add table
Add a link
Reference in a new issue