[ADD] developer/howto: guide for theming
A complete guide on how to create a custom website theme for Odoo closes odoo/documentation#4399 Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com> Signed-off-by: Castillo Jonathan (jcs) <jcs@odoo.com>
@ -645,6 +645,8 @@ Dependencies
|
||||
<the wkhtmltopdf download page_>`_ for it to support headers and footers. See our `wiki
|
||||
<https://github.com/odoo/odoo/wiki/Wkhtmltopdf>`_ for more details on the various versions.
|
||||
|
||||
.. _setup/install/source/running_odoo:
|
||||
|
||||
Running Odoo
|
||||
------------
|
||||
|
||||
|
@ -17,6 +17,7 @@ How-to guides
|
||||
howtos/create_reports
|
||||
howtos/accounting_localization
|
||||
howtos/translations
|
||||
howtos/website_themes
|
||||
howtos/provide_iap_services
|
||||
howtos/connect_device
|
||||
|
||||
@ -68,6 +69,11 @@ How-to guides
|
||||
|
||||
Learn how to provide translation abilities to your module.
|
||||
|
||||
.. card:: Website themes
|
||||
:target: howtos/website_themes
|
||||
|
||||
Learn how to customize your website by creating a custom theme.
|
||||
|
||||
.. card:: Provide IAP services
|
||||
:target: howtos/provide_iap_services
|
||||
|
||||
|
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 724 B |
Before Width: | Height: | Size: 155 KiB |
Before Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 9.4 KiB |
37
content/developer/howtos/website_themes.rst
Normal file
@ -0,0 +1,37 @@
|
||||
:show-content:
|
||||
:hide-page-toc:
|
||||
:show-toc:
|
||||
|
||||
==============
|
||||
Website themes
|
||||
==============
|
||||
|
||||
.. image:: website_themes/web-design.png
|
||||
:alt: Artistic illustration of "Web design"
|
||||
:width: 600
|
||||
|
||||
The Odoo Website Builder is an excellent tool for creating a website fully integrated with other
|
||||
Odoo apps. Using the theme's options and building blocks is easy and allows you to personalize your
|
||||
web presence the way you want. However, you can take things even further.
|
||||
|
||||
In this documentation, you will learn to completely customize your website without touching Odoo's
|
||||
core files, and this way, preserve the editing options of the Website Builder.
|
||||
|
||||
The information compiled in this documentation is based on our past experiences - both failures and
|
||||
successes. We invite you to use it as a base to build your own website and adapt it to your needs.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
website_themes/setup
|
||||
website_themes/theming
|
||||
website_themes/layout
|
||||
website_themes/navigation
|
||||
website_themes/pages
|
||||
website_themes/building_blocks
|
||||
website_themes/shapes
|
||||
website_themes/gradients
|
||||
website_themes/animations
|
||||
website_themes/forms
|
||||
website_themes/translations
|
||||
website_themes/going_live
|
44
content/developer/howtos/website_themes/animations.rst
Normal file
@ -0,0 +1,44 @@
|
||||
==========
|
||||
Animations
|
||||
==========
|
||||
|
||||
Eye-catching animations can bring your website to life.
|
||||
|
||||
On appearance
|
||||
=============
|
||||
|
||||
In standard, you can add animations to columns when they appear, thanks to the Website Builder. Odoo
|
||||
detects when your element is in the viewport and launches the animation. A large selection of
|
||||
animations is available:
|
||||
|
||||
- Fade in
|
||||
- Bounce in
|
||||
- Rotate in
|
||||
- Zoom in
|
||||
- …
|
||||
|
||||
You can easily define an animation on a column in your custom theme. You need to add two classes:
|
||||
`o_animate` and `o_anim_fade_in`. The second class changes depending on the type of animation you
|
||||
want to use.
|
||||
|
||||
Add the `o_animate_both_scroll` class to launch the animation every time the column appears on the
|
||||
screen. The animation is only launched once by default.
|
||||
|
||||
You can also define an `animation-duration` and an `animation-delay` directly in the `style`
|
||||
attribute.
|
||||
|
||||
**Use**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="col-lg-6 o_animate o_anim_fade_in o_animate_both_scroll" style="animation-duration: 2s !important; animation-delay: 1s !important;">
|
||||
<h2>A Section Subtitle</h2>
|
||||
<p>Write one or two paragraphs describing your product or services.</p>
|
||||
</div>
|
||||
|
||||
.. image:: animations/animations.png
|
||||
:alt: Animation options
|
||||
|
||||
.. seealso::
|
||||
`Website Animate
|
||||
<https://github.com/odoo/odoo/blob/34c0c9c1ae00aba391932129d4cefd027a9c6bbd/addons/website/static/src/scss/website.scss#L1638>`_
|
After Width: | Height: | Size: 12 KiB |
503
content/developer/howtos/website_themes/building_blocks.rst
Normal file
@ -0,0 +1,503 @@
|
||||
===============
|
||||
Building blocks
|
||||
===============
|
||||
|
||||
Building blocks, also known as snippets, are how users design and layout pages. They are important
|
||||
XML elements of your design.
|
||||
|
||||
The building blocks are classified into four categories:
|
||||
|
||||
#. **Structure blocks**: to give a basic structure to the website
|
||||
#. **Feature blocks**: to describe the features of a product or service
|
||||
#. **Dynamic Content blocks**: blocks that are animated or interact with the backend
|
||||
#. **Inner Content blocks**: blocks used inside other building blocks
|
||||
|
||||
In this chapter, you will learn how to create custom building blocks and options.
|
||||
|
||||
File structure
|
||||
==============
|
||||
|
||||
The layout's file structure is the following.
|
||||
|
||||
::
|
||||
|
||||
views
|
||||
├── snippets
|
||||
│ └── options.xml
|
||||
│ └── s_snippet_name.xml
|
||||
|
||||
The styles' file structure is the following.
|
||||
|
||||
::
|
||||
|
||||
static
|
||||
├── src
|
||||
│ └── snippets
|
||||
│ └── options.scss
|
||||
│ └── s_snippet_name
|
||||
│ └── 000.js
|
||||
│ └── 000.scss
|
||||
│ └── 000.xml
|
||||
│ └── option.js
|
||||
|
||||
.. seealso::
|
||||
`XML templates of the different snippets
|
||||
<{GITHUB_PATH}/addons/website/views/snippets/snippets.xml>`_
|
||||
|
||||
.. admonition:: Demo page
|
||||
|
||||
http://localhost:8069/website/demo/snippets
|
||||
|
||||
Layout
|
||||
======
|
||||
|
||||
Snippets are editable by the user using the Website Builder. Some Bootstrap classes are important as
|
||||
**they trigger some Website Builder options**.
|
||||
|
||||
Wrapper
|
||||
-------
|
||||
|
||||
The standard main container of any snippet is a `section`. Any section element can be edited like a
|
||||
block of content that you can move or duplicate.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section class="s_snippet_name" data-name="..." data-snippet="...">
|
||||
<!-- Content -->
|
||||
</section>
|
||||
|
||||
For inner content snippets, any other HTML tag can be used.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="s_snippet_name" data-name="..." data-snippet="...">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
|
||||
.. todo:: Missing description in table ...
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - class
|
||||
- Unique class name for this snippet
|
||||
* - data-name
|
||||
- Displayed in the right panel as the name of the snippet. If not found, it will fall back to
|
||||
*Block*.
|
||||
* - data-snippet
|
||||
- Used by the system to identify the snippet
|
||||
|
||||
The system automatically adds the `data-name` and `data-snippet` attributes during the drag and
|
||||
drop based on the template's name.
|
||||
|
||||
.. warning::
|
||||
Those attributes should be specifically added when a snippet is declared on a theme page.
|
||||
|
||||
.. warning::
|
||||
Avoid adding a `section` tag inside another `section` tag: this will trigger twice the Website
|
||||
Builder's options. You can use inner content snippets instead.
|
||||
|
||||
Columns
|
||||
-------
|
||||
|
||||
Any large Bootstrap columns directly descending from a `.row` element (respecting Bootstrap
|
||||
structure) will be triggered by the Website Builder to make them resizable.
|
||||
|
||||
.. code-block:: css
|
||||
|
||||
.row > .col-lg-*
|
||||
|
||||
Add padding on columns and sections.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
class="pt80 pb80"
|
||||
|
||||
Add a background based on the color palette for columns and sections.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
class="o_cc o_cc*"
|
||||
|
||||
Make an element not editable.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="o_not_editable">
|
||||
|
||||
Enable the columns selector.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="container s_allow_columns">
|
||||
|
||||
Disable the columns option.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="row s_nb_column_fixed">
|
||||
|
||||
Disable the size option of all child columns.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="row s_col_no_resize">
|
||||
|
||||
Disable the size option for one column.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="col-lg-* s_col_no_resize">
|
||||
|
||||
Disable the background color option for all columns.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="row s_col_no_bgcolor">
|
||||
|
||||
Disable the background color option of one column.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="col-lg-* s_col_no_bgcolor">
|
||||
|
||||
Add parallax effect.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section class="parallax s_parallax_is_fixed s_parallax_no_overflow_hidden" data-scroll-background-ratio="1">
|
||||
<span class="s_parallax_bg oe_img_bg o_bg_img_center" style="background-image: url('...'); background-position: 50% 75%;"/>
|
||||
<div class="container">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Add a black color filter with an opacity of 50%.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section>
|
||||
<div class="o_we_bg_filter bg-black-50"/>
|
||||
<div class="container">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Add a white color filter with an opacity of 85%.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section>
|
||||
<div class="o_we_bg_filter bg-white-85"/>
|
||||
<div class="container">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Add a custom color filter.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section>
|
||||
<div class="o_we_bg_filter" style="background-color: rgba(39, 110, 114, 0.54) !important;"/>
|
||||
<div class="container">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Add a custom gradient filter.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section>
|
||||
<div class="o_we_bg_filter" style="background-image: linear-gradient(135deg, rgba(255, 204, 51, 0.5) 0%, rgba(226, 51, 255, 0.5) 100%) !important;"/>
|
||||
<div class="container">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Styles
|
||||
======
|
||||
|
||||
Compatibility system
|
||||
--------------------
|
||||
|
||||
When a snippet has a `data-vcss` or `data-vjs` attribute, it means it is an updated version, not the
|
||||
original one.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section class="s_snippet_name" data-vcss="..." data-js="...">
|
||||
<!-- Content -->
|
||||
</section>
|
||||
|
||||
The `data-vcss` and `data-js` attributes indicate to the system which file version to load for that
|
||||
snippet (e.g., :file:`001.js`, :file:`002.scss`).
|
||||
|
||||
Custom
|
||||
======
|
||||
|
||||
Create the snippet's content.
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/snippets/s_airproof_snippet.xml``
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="s_airproof_snippet" name="...">
|
||||
<section class="s_airproof_snippet">
|
||||
<!-- Content -->
|
||||
</section>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
.. warning::
|
||||
`data-name` and `data-snippet` attributes have to be specified when a snippet is declared on a
|
||||
theme page.
|
||||
|
||||
.. tip::
|
||||
- Use Bootstrap native classes as much as possible.
|
||||
- Prefix all your custom classes.
|
||||
- Use underscore lowercase notation to name classes, e.g., `.x_nav`, `.x_nav_item`.
|
||||
- Avoid using ID tag.
|
||||
|
||||
Add your custom snippet to the list of default snippets, so the user can drag and drop it on the
|
||||
page, directly from the edit panel.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/snippets/options.xml``
|
||||
|
||||
<template id="snippets" inherit_id="website.snippets" name="Custom Snippets">
|
||||
<xpath expr="//*[@id='default_snippets']" position="before">
|
||||
<t id="x_theme_snippets">
|
||||
<div id="x_theme_snippets_category" class="o_panel">
|
||||
<div class="o_panel_header">Theme</div>
|
||||
<div class="o_panel_body">
|
||||
<t t-snippet="website_airproof.s_airproof_snippet" t-thumbnail="/website_airproof/static/src/img/wbuilder/s_airproof_snippet.svg">
|
||||
<keywords>Snippet</keywords>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - t-snippet
|
||||
- The template to use
|
||||
* - t-thumbnail
|
||||
- The path to the snippet thumbnail
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
Options allow users to edit a snippet's appearance using the Website Builder. You can create
|
||||
snippet options easily and automatically add them to the Website Builder.
|
||||
|
||||
Groups properties
|
||||
-----------------
|
||||
|
||||
Options are wrapped in groups. Groups can have properties that define how the included options
|
||||
interact with the user interface.
|
||||
|
||||
`data-selector` binds all the options included in the group to a particular element. It can be used
|
||||
in combination with `data-target` and `data-exclude`.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div data-selector="section, h1, .custom_class, #custom_id">
|
||||
|
||||
`data-js` binds custom JavaScript methods.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div data-js="CustomMethodName" data-selector="...">
|
||||
|
||||
`data-drop-in` defines the list of elements where the snippet can be dropped into.
|
||||
|
||||
.. todo:: no css selector ...
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div data-selector="..." data-drop-in="...">
|
||||
|
||||
`data-drop-near` defines the list of elements where the snippet can be dropped beside.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div data-selector="..." data-drop-near="...">
|
||||
|
||||
SCSS options
|
||||
------------
|
||||
|
||||
Options can apply standard or custom CSS classes to the snippet. Depending on the method that you
|
||||
choose, the user interface will behave differently.
|
||||
|
||||
`data-select-class="..."`
|
||||
|
||||
More `data-select-class` in the same group defines a list of classes the user can apply. Only one
|
||||
option can be enabled at a time.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/snippets/options.xml``
|
||||
|
||||
<template id="snippet_options" inherit_id="website.snippet_options" name="...">
|
||||
<xpath expr="." position="inside">
|
||||
|
||||
<div data-selector="h1, h2, h3, h4, h5, h6">
|
||||
<we-select string="Headings">
|
||||
<we-button data-select-class="">Default</we-button>
|
||||
<we-button data-select-class="x_custom_class_01">01</we-button>
|
||||
<we-button data-select-class="x_custom_class_02">02</we-button>
|
||||
</we-select>
|
||||
</div>
|
||||
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
.. seealso::
|
||||
`XML templates of the different snippets
|
||||
<{GITHUB_PATH}/addons/website/views/snippets/snippets.xml>`_
|
||||
|
||||
JavaScript options
|
||||
------------------
|
||||
|
||||
The `data-js` attribute can be assigned to an options group in order to define a custom method.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module */
|
||||
|
||||
import options from 'web_editor.snippets.options';
|
||||
|
||||
options.registry.CustomMethodName = options.Class.extend({
|
||||
//
|
||||
});
|
||||
|
||||
The Website Builder provides several events you can use to trigger your custom functions.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Event
|
||||
- Description
|
||||
* - start
|
||||
- Occurs when the publisher selects the snippet for the first time in an editing session or
|
||||
when the snippet is drag-and-dropped on the page.
|
||||
* - onFocus
|
||||
- Occurs each time the snippet is selected by the user or when the snippet is drag-and-dropped
|
||||
on the page.
|
||||
* - onBlur
|
||||
- Occurs when a snippet loses focus.
|
||||
* - onClone
|
||||
- Occurs just after a snippet is duplicated.
|
||||
* - onRemove
|
||||
- Occurs just before the snippet is removed.
|
||||
* - onBuilt
|
||||
- Occurs just after the snippet is drag-and-dropped on a drop zone. When this event is
|
||||
triggered, the content is already inserted in the page.
|
||||
* - cleanForSave
|
||||
- Occurs before the publisher saves the page.
|
||||
|
||||
Dynamic Content templates
|
||||
-------------------------
|
||||
|
||||
By default, Dynamic Content blocks have a selection of templates available in the Website Builder.
|
||||
You can also add your own template to the list.
|
||||
|
||||
Blog posts
|
||||
~~~~~~~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/snippets/options.xml``
|
||||
|
||||
<template id="dynamic_filter_template_blog_post_airproof" name="...">
|
||||
<div t-foreach="records" t-as="data" class="s_blog_posts_post">
|
||||
<t t-set="record" t-value="data['_record']"/>
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - id
|
||||
- The ID of the template. Has to start with `dynamic_filter_template_blog_post_`
|
||||
* - name
|
||||
- Human-readable name of the template
|
||||
|
||||
Products
|
||||
~~~~~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/snippets/options.xml``
|
||||
|
||||
<template id="dynamic_filter_template_product_product_airproof" name="...">
|
||||
<t t-foreach="records" t-as="data" data-number-of-elements="4" data-number-of-elements-sm="1" data-number-of-elements-fetch="8">
|
||||
<t t-set="record" t-value="data['_record']"/>
|
||||
<!-- Content -->
|
||||
</t>
|
||||
</template>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 40 60
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - id
|
||||
- The ID of the template. Has to start with `dynamic_filter_template_product_product_`
|
||||
* - name
|
||||
- Human-readable name of the template
|
||||
* - data-number-of-elements
|
||||
- Number of products per slide on desktop
|
||||
* - data-number-of-elements-sm
|
||||
- Number of products per slide on mobile
|
||||
* - data-number-of-elements-fetch
|
||||
- The total amount of fetched products
|
||||
|
||||
Events
|
||||
~~~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/snippets/options.xml``
|
||||
|
||||
<template id="dynamic_filter_template_event_event_airproof" name="...">
|
||||
<div t-foreach="records" t-as="data" class="s_events_event">
|
||||
<t t-set="record" t-value="data['_record']._set_tz_context()"/>
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - id
|
||||
- The ID of the template. Has to start with `dynamic_filter_template_event_event_`
|
||||
* - name
|
||||
- Human-readable name of the template
|
134
content/developer/howtos/website_themes/forms.rst
Normal file
@ -0,0 +1,134 @@
|
||||
=====
|
||||
Forms
|
||||
=====
|
||||
|
||||
Forms in Odoo are very powerful. They are directly integrated with other applications and can be
|
||||
used for many different purposes.
|
||||
|
||||
In this chapter, you will discover how to:
|
||||
|
||||
- Add a form in your custom theme.
|
||||
- Change the action of the form.
|
||||
- Stylize the form thanks to Bootstrap variables.
|
||||
|
||||
Default form
|
||||
============
|
||||
|
||||
To add a form to your page, you can simply copy and paste the code generated by the Website Builder
|
||||
in your view.
|
||||
|
||||
It should look something like the following.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<form action="/website/form/" method="post" enctype="multipart/form-data" class="o_mark_required" data-mark="*" data-pre-fill="true" data-success-mode="redirect" data-success-page="/contactus-thank-you" data-model_name="mail.mail">
|
||||
<div class="s_website_form_rows row s_col_no_bgcolor">
|
||||
<div class="form-group s_website_form_field col-12 s_website_form_dnone" data-name="Field">
|
||||
<!-- form fields -->
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
Actions
|
||||
=======
|
||||
|
||||
There is a `data-model_name` in the form tag. It enables you to define different actions for your
|
||||
form.
|
||||
|
||||
Send an email (this action is used by default).
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<form data-model_name="mail.mail">
|
||||
|
||||
Apply for a job.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<form data-model_name="hr.applicant">
|
||||
|
||||
Create a customer.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<form data-model_name="res.partner">
|
||||
|
||||
Create a ticket.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<form data-model_name="helpdesk.ticket">
|
||||
|
||||
Create an opportunity.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<form data-model_name="crm.lead">
|
||||
|
||||
Create a task.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<form data-model_name="project.task">
|
||||
|
||||
Success
|
||||
=======
|
||||
|
||||
You can also define what happens once the form is submitted thanks to the `data-success-mode`.
|
||||
|
||||
Redirect the user to a page defined in the `data-success-page`.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<form data-success-mode="redirect" data-success-page="/contactus-thank-you">
|
||||
|
||||
Show a message (on the same page).
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<form data-success-mode="message">
|
||||
|
||||
You can add your success message directly under the form tag. Always add the `d-none` class to make
|
||||
sure that your success message is hidden if the form hasn't been submitted.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="s_website_form_end_message d-none">
|
||||
<div class="oe_structure">
|
||||
<section class="s_text_block pt64 pb64" data-snippet="s_text_block">
|
||||
<div class="container">
|
||||
<h2 class="text-center">This is a success!</h2>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Bootstrap variables
|
||||
===================
|
||||
|
||||
As you already know, the Website Builder creates content based on Bootstrap. This is also true for
|
||||
forms. Below you can find a selection of Bootstrap variables, or check out the `full list of
|
||||
variables <https://github.com/twbs/bootstrap/blob/main/scss/_variables.scss>`_.
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/bootstrap_overridden.scss``
|
||||
|
||||
$input-padding-y: $input-btn-padding-y !default;
|
||||
$input-padding-x: $input-btn-padding-x !default;
|
||||
|
||||
$input-font-family: $input-btn-font-family !default;
|
||||
$input-font-size: $input-btn-font-size !default;
|
||||
$input-font-weight: $font-weight-base !default;
|
||||
$input-line-height: $input-btn-line-height !default;
|
||||
|
||||
$input-color: $gray-700 !default;
|
||||
$input-border-color: $gray-400 !default;
|
||||
$input-border-width: $input-btn-border-width !default;
|
||||
$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;
|
||||
$input-border-radius: $border-radius !default;
|
||||
|
||||
$input-focus-bg: $input-bg !default;
|
||||
$input-focus-border-color: lighten($component-active-bg, 25%) !default;
|
||||
$input-focus-color: $input-color !default;
|
||||
$input-focus-width: $input-btn-focus-width !default;
|
||||
$input-focus-box-shadow: $input-btn-focus-box-shadow !default;
|
40
content/developer/howtos/website_themes/going_live.rst
Normal file
@ -0,0 +1,40 @@
|
||||
==========
|
||||
Going live
|
||||
==========
|
||||
|
||||
Once you have finished all the web design and development work, it's time to deploy it on a
|
||||
development or production database.
|
||||
|
||||
Module import
|
||||
=============
|
||||
|
||||
Odoo SaaS
|
||||
---------
|
||||
|
||||
Follow these steps the first time you import a module:
|
||||
|
||||
#. Create a ZIP file of your module.
|
||||
#. Connect to the project database.
|
||||
#. Enable the :ref:`developer mode <developer-mode>`.
|
||||
#. Go to :guilabel:`Apps`, search for `base_import_module`, and install it if necessary.
|
||||
#. Click on :guilabel:`Import Module` in the menu.
|
||||
#. Upload your ZIP file, tick :guilabel:`Force init`, and click the :guilabel:`Import App` button.
|
||||
|
||||
If you need to re-import a module after making some changes, follow the same steps, but before
|
||||
importing the module, open the developer menu and select :guilabel:`Become Superuser`. To leave the
|
||||
Superuser mode, log out and log back in.
|
||||
|
||||
.. warning::
|
||||
The ZIP file size must be less than 50 MB.
|
||||
|
||||
.. seealso::
|
||||
- `Odoo eLearning: Register a Free Domain Name <https://www.odoo.com/slides/slide/register-a-free-domain-name-1663>`_
|
||||
|
||||
Odoo.sh
|
||||
-------
|
||||
|
||||
Go to :guilabel:`Apps` and click on :guilabel:`Update Apps List` in the menu. Search for your module
|
||||
in the list and install it.
|
||||
|
||||
.. seealso::
|
||||
:doc:`Introduction to Odoo.sh <../../../administration/odoo_sh/overview/introduction>`
|
52
content/developer/howtos/website_themes/gradients.rst
Normal file
@ -0,0 +1,52 @@
|
||||
=========
|
||||
Gradients
|
||||
=========
|
||||
|
||||
In this chapter, you will discover how to:
|
||||
|
||||
- Add a gradient to a section or a title.
|
||||
- Add your own gradient to the Website Builder palette.
|
||||
|
||||
Standard
|
||||
========
|
||||
|
||||
In standard, you can select several gradients directly from the Website Builder. However, for custom
|
||||
themes, you must add the gradients directly in the section tag with a style attribute.
|
||||
|
||||
**Use**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section class="s_text_image" data-snippet="s_text_image" data-name="Text - Image" style="background-image: linear-gradient(135deg, rgb(255, 204, 51) 0%, rgb(226, 51, 255) 100%) !important;">
|
||||
<!-- Content -->
|
||||
</section>
|
||||
|
||||
To apply a gradient to text, use a font tag with the `text-gradient` class.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<h2>
|
||||
<font class="text-gradient" style="background-image: linear-gradient(135deg, rgb(203, 94, 238) 0%, rgb(75, 225, 236) 100%);">A Section Subtitle</font>
|
||||
</h2>
|
||||
|
||||
Custom
|
||||
======
|
||||
|
||||
You can also add your own custom gradients to the Website Builder. This way, the user can easily
|
||||
use them without manually recreating them.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/presets.xml``
|
||||
|
||||
<record id="colorpicker" model="ir.ui.view">
|
||||
<field name="key">website_airproof.colorpicker</field>
|
||||
<field name="name">Custom Gradients</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="inherit_id" ref="web_editor.colorpicker"/>
|
||||
<field name="website_id">1</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//*[@data-name='predefined_gradients']/*" position="before">
|
||||
<button class="w-50 o_we_color_btn" style="background-image: linear-gradient(145deg, rgb(5, 85, 94) 0%, rgb(0, 131, 148) 100%);" data-color="linear-gradient(145deg, rgb(5, 85, 94) 0%, rgb(0, 131, 148) 100%)"></button>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
619
content/developer/howtos/website_themes/layout.rst
Normal file
@ -0,0 +1,619 @@
|
||||
======
|
||||
Layout
|
||||
======
|
||||
|
||||
In this chapter, you will learn how to:
|
||||
|
||||
- Create a custom header.
|
||||
- Create a custom footer.
|
||||
- Modify a standard template.
|
||||
- Add a copyright section.
|
||||
- Improve your website's responsiveness.
|
||||
|
||||
Default
|
||||
=======
|
||||
|
||||
An Odoo page combines cross-page and unique elements. Cross-page elements are the same on every
|
||||
page, while unique elements are only related to a specific page. By default, a page has two
|
||||
cross-page elements, the header and the footer, and a unique main element that contains the specific
|
||||
content of that page.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div id="wrapwrap">
|
||||
<header/>
|
||||
<main>
|
||||
<div id="wrap" class="oe_structure">
|
||||
<!-- Page Content -->
|
||||
</div>
|
||||
</main>
|
||||
<footer/>
|
||||
</div>
|
||||
|
||||
Any Odoo XML file starts with encoding specifications. After that, you must write your code inside
|
||||
an `<odoo>` tag.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
...
|
||||
</odoo>
|
||||
|
||||
.. note::
|
||||
Using precise file names is important to find information through all modules quickly. File names
|
||||
should only contain lowercase alphanumerics and underscores.
|
||||
|
||||
Always add an empty line at the end of your file. This can be done automatically by configuring
|
||||
your IDE.
|
||||
|
||||
XPath
|
||||
=====
|
||||
|
||||
XPath (XML Path Language) is an expression language that enables you to navigate through elements
|
||||
and attributes in an XML document easily. XPath is used to extend standard Odoo templates.
|
||||
|
||||
A view is coded the following way.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<template id="..." inherit_id="..." name="...">
|
||||
<!-- Content -->
|
||||
</template>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - id
|
||||
- ID of the modified view
|
||||
* - inherited_id
|
||||
- ID of the standard view
|
||||
* - name
|
||||
- Human-readable name of the modified view
|
||||
|
||||
For each XPath, you modify two attributes: **expression** and **position**.
|
||||
|
||||
.. example::
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/website_templates.xml``
|
||||
|
||||
<template id="layout" inherit_id="website.layout" name="Welcome Message">
|
||||
<xpath expr="//header" position="before">
|
||||
<!-- Content -->
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
This XPath adds a welcome message right before the page content.
|
||||
|
||||
.. warning::
|
||||
Be careful when replacing default elements' attributes. As your theme extends the default one,
|
||||
your changes will take priority over any future Odoo update.
|
||||
|
||||
.. note::
|
||||
- You should update your module every time you create a new template or record.
|
||||
- *XML IDs* of inheriting views should use the same *ID* as the original record. It helps to find
|
||||
all inheritance at a glance. As final *XML IDs* are prefixed by the module that creates them,
|
||||
there is no overlap.
|
||||
|
||||
Expressions
|
||||
-----------
|
||||
|
||||
XPath uses path expressions to select nodes in an XML document. Selectors are used inside the
|
||||
expression to target the right element. The most useful ones are listed below.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Descendent selectors
|
||||
- Description
|
||||
* - /
|
||||
- Selects from the root node.
|
||||
* - //
|
||||
- Selects nodes in the document from the current node that matches the selection no matter
|
||||
where they are.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute selectors
|
||||
- Description
|
||||
* - \*
|
||||
- Selects any XML tag. `*` can be replaced by a specific tag if the selection needs to be
|
||||
more precise.
|
||||
* - \*[@id="id"]
|
||||
- Selects a specific ID.
|
||||
* - \*[hasclass("class")]
|
||||
- Selects a specific class.
|
||||
* - \*[@name="name"]
|
||||
- Selects a tag with a specific name.
|
||||
* - \*[@t-call="t-call"]
|
||||
- Selects a specific t-call.
|
||||
|
||||
Position
|
||||
--------
|
||||
|
||||
The position defines where the code is placed inside the template. The possible values are listed
|
||||
below:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Position
|
||||
- Description
|
||||
* - replace
|
||||
- Replaces the targeted node with the XPath content.
|
||||
* - inside
|
||||
- Adds the XPath content inside the targeted node.
|
||||
* - before
|
||||
- Adds the XPath content before the targeted node.
|
||||
* - after
|
||||
- Adds the XPath content after the targeted node.
|
||||
* - attributes
|
||||
- Adds the XPath content inside an attribute.
|
||||
|
||||
.. example::
|
||||
This XPath adds a `<div>` before the `<nav>` that is a direct child of the `<header>`.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<xpath expr="//header/nav" position="before">
|
||||
<div>Some content before the header</div>
|
||||
</xpath>
|
||||
|
||||
This XPath adds `x_airproof_header` in the class attribute of the header. You also need to define
|
||||
a `separator` attribute to add a space before the class you are adding.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<xpath expr="//header" position="attributes">
|
||||
<attribute name="class" add="x_airproof_header" separator=" "/>
|
||||
</xpath>
|
||||
|
||||
This XPath removes `x_airproof_header` in the class attribute of the header. In this case, you
|
||||
don't need to use the `separator` attribute.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<xpath expr="//header" position="attributes">
|
||||
<attribute name="class" remove="x_airproof_header" />
|
||||
</xpath>
|
||||
|
||||
This XPath removes the first element with a `.breadcrumb` class.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<xpath expr="//*[hasclass('breadcrumb')]" position="replace"/>
|
||||
|
||||
This XPath adds an extra `<li>` element after the last child of the `<ul>` element.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<xpath expr="//ul" position="inside">
|
||||
<li>Last element of the list</li>
|
||||
</xpath>
|
||||
|
||||
.. seealso::
|
||||
You can find more information about XPath in this `cheat sheet <https://devhints.io/xpath>`_.
|
||||
|
||||
QWeb
|
||||
====
|
||||
|
||||
QWeb is the primary templating engine used by Odoo. It is an XML templating engine mainly used to
|
||||
generate HTML fragments and pages.
|
||||
|
||||
.. seealso::
|
||||
:doc:`QWeb templates documentation <../../reference/frontend/qweb>`.
|
||||
|
||||
Background
|
||||
==========
|
||||
|
||||
You can define a color or an image as the background of your website.
|
||||
|
||||
**Colors**
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-color-palettes: map-merge($o-color-palettes,
|
||||
(
|
||||
'airproof': (
|
||||
'o-cc1-bg': 'o-color-5',
|
||||
'o-cc5-bg': 'o-color-1',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
**Image/pattern**
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-website-values-palettes: (
|
||||
(
|
||||
'body-image': '/website_airproof/static/src/img/background-lines.svg',
|
||||
'body-image-type': 'image' or 'pattern'
|
||||
)
|
||||
);
|
||||
|
||||
Header
|
||||
======
|
||||
|
||||
By default, the header contains a responsive navigation menu and the company's logo. You can easily
|
||||
add new elements or create your own template.
|
||||
|
||||
Standard
|
||||
--------
|
||||
|
||||
Enable one of the header default templates.
|
||||
|
||||
.. important::
|
||||
Don't forget that you may need to disable the active header template first.
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-website-values-palettes: (
|
||||
(
|
||||
'header-template': 'Contact',
|
||||
),
|
||||
);
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/presets.xml``
|
||||
|
||||
<record id="website.template_header_contact" model="ir.ui.view">
|
||||
<field name="active" eval="True"/>
|
||||
</record>
|
||||
|
||||
Custom
|
||||
------
|
||||
|
||||
Create your own template and add it to the list.
|
||||
|
||||
.. important::
|
||||
Don't forget that you may need to disable the active header template first.
|
||||
|
||||
**Option**
|
||||
|
||||
Use the following code to add an option for your new custom header on the Website Builder.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/presets.xml``
|
||||
|
||||
<template id="template_header_opt" inherit_id="website.snippet_options" name="Header Template - Option">
|
||||
<xpath expr="//we-select[@data-variable='header-template']" position="inside">
|
||||
<we-button title="airproof"
|
||||
data-customize-website-views="website_airproof.header"
|
||||
data-customize-website-variable="'airproof'" data-img="/website_airproof/static/src/img/wbuilder/template_header_opt.svg"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - data-customize-website-views
|
||||
- The template to enable
|
||||
* - data-customize-website-variable
|
||||
- The name given to the variable
|
||||
* - data-img
|
||||
- The thumbnail of the custom template shown in the templates selection on the Website Builder
|
||||
|
||||
Now you have to explicitly define that you want to use your custom template in the Odoo SASS
|
||||
variables.
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-website-values-palettes: (
|
||||
(
|
||||
'header-template': 'airproof',
|
||||
),
|
||||
);
|
||||
|
||||
**Layout**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/website_templates.xml``
|
||||
|
||||
<record id="header" model="ir.ui.view">
|
||||
<field name="name">Airproof Header</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="key">website_airproof.header</field>
|
||||
<field name="inherit_id" ref="website.layout"/>
|
||||
<field name="mode">extension</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//header//nav" position="replace">
|
||||
<!-- Static Content -->
|
||||
<!-- Components -->
|
||||
<!-- Editable areas -->
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Components
|
||||
----------
|
||||
|
||||
In your custom header, you can call several sub-templates using the `t-call` directive from QWeb:
|
||||
|
||||
Logo
|
||||
~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-call="website.placeholder_header_brand">
|
||||
<t t-set="_link_class" t-valuef="..."/>
|
||||
</t>
|
||||
|
||||
Don't forget to record the logo of your website in the database.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/images.xml``
|
||||
|
||||
<record id="website.default_website" model="website">
|
||||
<field name="logo" type="base64" file="website_airproof/static/src/img/content/logo.png"/>
|
||||
</record>
|
||||
|
||||
Menu
|
||||
~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-foreach="website.menu_id.child_id" t-as="submenu">
|
||||
<t t-call="website.submenu">
|
||||
<t t-set="item_class" t-valuef="nav-item"/>
|
||||
<t t-set="link_class" t-valuef="nav-link"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
Sign in
|
||||
~~~~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-call="portal.placeholder_user_sign_in">
|
||||
<t t-set="_item_class" t-valuef="nav-item"/>
|
||||
<t t-set="_link_class" t-valuef="nav-link"/>
|
||||
</t>
|
||||
|
||||
User dropdown
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-call="portal.user_dropdown">
|
||||
<t t-set="_user_name" t-value="true"/>
|
||||
<t t-set="_icon" t-value="false"/>
|
||||
<t t-set="_avatar" t-value="false"/>
|
||||
<t t-set="_item_class" t-valuef="nav-item dropdown"/>
|
||||
<t t-set="_link_class" t-valuef="nav-link"/>
|
||||
<t t-set="_dropdown_menu_class" t-valuef="..."/>
|
||||
</t>
|
||||
|
||||
Language selector
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-call="website.placeholder_header_language_selector">
|
||||
<t t-set="_div_classes" t-valuef="..."/>
|
||||
</t>
|
||||
|
||||
Call to action
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-call="website.placeholder_header_call_to_action">
|
||||
<t t-set="_div_classes" t-valuef="..."/>
|
||||
</t>
|
||||
|
||||
Navbar toggler
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-call="website.navbar_toggler">
|
||||
<t t-set="_toggler_class" t-valuef="..."/>
|
||||
</t>
|
||||
|
||||
.. seealso::
|
||||
You can add a :ref:`header overlay <header_overlay>` to position your header over the content of
|
||||
your page. It has to be done on each page individually.
|
||||
|
||||
Footer
|
||||
======
|
||||
|
||||
By default, the footer contains a section with some static content. You can easily add new elements
|
||||
or create your own template.
|
||||
|
||||
Standard
|
||||
--------
|
||||
|
||||
Enable one of the default footer templates. Don't forget that you may need to disable the active
|
||||
footer template first.
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-website-values-palettes: (
|
||||
(
|
||||
'header-template': 'Contact',
|
||||
),
|
||||
);
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/presets.xml``
|
||||
|
||||
<record id="website.template_header_contact" model="ir.ui.view">
|
||||
<field name="active" eval="True"/>
|
||||
</record>
|
||||
|
||||
Custom
|
||||
------
|
||||
|
||||
Create your own template and add it to the list. Don't forget that you may need to disable the
|
||||
active footer template first.
|
||||
|
||||
**Option**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/presets.xml``
|
||||
|
||||
<template id="template_header_opt" inherit_id="website.snippet_options" name="Footer Template - Option">
|
||||
<xpath expr="//we-select[@data-variable='footer-template']" position="inside">
|
||||
<we-button title="airproof"
|
||||
data-customize-website-views="website_airproof.footer"
|
||||
data-customize-website-variable="'airproof'"
|
||||
data-img="/website_airproof/static/src/img/wbuilder/template_header_opt.svg"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-website-values-palettes: (
|
||||
(
|
||||
'footer-template': 'airproof',
|
||||
),
|
||||
);
|
||||
|
||||
**Layout**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/website_templates.xml``
|
||||
|
||||
<record id="footer" model="ir.ui.view">
|
||||
<field name="name">Airproof Footer</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="key">website_airproof.footer</field>
|
||||
<field name="inherit_id" ref="website.layout"/>
|
||||
<field name="mode">extension</field>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@id='footer']" position="replace">
|
||||
<div id="footer" class="oe_structure oe_structure_solo" t-ignore="true" t-if="not no_footer">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
There is only one template available at the moment for the copyright bar.
|
||||
|
||||
To replace the content or modify its structure, you can add your own code to the following XPath.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/website_templates.xml``
|
||||
|
||||
<template id="copyright" inherit_id="website.layout">
|
||||
<xpath expr="//div[hasclass('o_footer_copyright')]" position="replace">
|
||||
<div class="o_footer_copyright" data-name="Copyright">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
Drop zone
|
||||
=========
|
||||
|
||||
Instead of defining the complete layout of a page, you can create building blocks (snippets) and
|
||||
let the user choose where to drag and drop them, creating the page layout on their own. We call
|
||||
this *modular design*.
|
||||
|
||||
You can define an empty area that the user can fill with snippets.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div id="oe_structure_layout_01" class="oe_structure"/>
|
||||
|
||||
.. todo:: Missing description in table ...
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Class
|
||||
- Description
|
||||
* - oe_structure
|
||||
- Define a drag-and-drop area for the user.
|
||||
* - oe_structure_solo
|
||||
- Only one snippet can be dropped in this area.
|
||||
|
||||
You can also populate an existing drop zone with your content.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<template id="oe_structure_layout_01" inherit_id="..." name="...">
|
||||
<xpath expr="//*[@id='oe_structure_layout_01']" position="replace">
|
||||
<div id="oe_structure_layout_01" class="oe_structure oe_structure_solo">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
Responsive
|
||||
==========
|
||||
|
||||
You can find some hints below to help you make your website responsive.
|
||||
|
||||
Bootstrap
|
||||
---------
|
||||
|
||||
.. seealso::
|
||||
- `Bootstrap documentation on responsive breakpoints
|
||||
<https://getbootstrap.com/docs/4.6/layout/overview/#responsive-breakpoints>`_
|
||||
- `Bootstrap documentation on display property
|
||||
<https://getbootstrap.com/docs/4.6/utilities/display/>`_
|
||||
|
||||
**Font size**
|
||||
|
||||
As of v4.3.0, Bootstrap ships with the option to enable responsive font sizes, allowing text to
|
||||
scale more naturally across device and viewport sizes. Enable them by changing the
|
||||
`$enable-responsive-font-sizes` Sass variable to true.
|
||||
|
||||
.. seealso::
|
||||
`Responsive Font Size GitHub <https://github.com/twbs/rfs/tree/v8.1.0>`_
|
||||
|
||||
Website Builder
|
||||
---------------
|
||||
|
||||
Hide a specific `<section>` on mobile.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section class="d-none d-md-block">
|
||||
<!-- Content -->
|
||||
</section>
|
||||
|
||||
Hide a `<col>` on mobile.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section>
|
||||
<div class="container">
|
||||
<div class="row d-flex align-items-stretch">
|
||||
<div class="col-lg-4 d-none d-md-block">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
212
content/developer/howtos/website_themes/navigation.rst
Normal file
@ -0,0 +1,212 @@
|
||||
==========
|
||||
Navigation
|
||||
==========
|
||||
|
||||
You can easily modify the navigation with the Website Builder to fit your needs.
|
||||
|
||||
In this chapter, you will learn how to:
|
||||
|
||||
- Delete and create menu items.
|
||||
- Create a dropdown menu.
|
||||
- Create a mega menu.
|
||||
|
||||
Default
|
||||
=======
|
||||
|
||||
Odoo automatically generates some basic menu items depending on the apps you installed. For example,
|
||||
the Website app adds two items to the main menu. These items are linked to pages, which are also
|
||||
automatically created.
|
||||
|
||||
Delete default menu items.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/menu.xml``
|
||||
|
||||
<!-- Contact us -->
|
||||
<delete model="website.menu" search="[('url','in', ['/', '/contactus']),
|
||||
('website_id', '=', 1)]"/>
|
||||
|
||||
<!-- Shop -->
|
||||
<delete model="website.menu" search="[('url','in', ['/', '/shop']),
|
||||
('website_id', '=', 1)]"/>
|
||||
|
||||
Menu item
|
||||
=========
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/menu.xml``
|
||||
|
||||
<record id="menu_about_us" model="website.menu">
|
||||
<field name="name">About us</field>
|
||||
<field name="url">/about-us</field>
|
||||
<field name="parent_id" search="[
|
||||
('url', '=', '/default-main-menu'),
|
||||
('website_id', '=', 1)]"/>
|
||||
<field name="website_id">1</field>
|
||||
<field name="sequence" type="int">10</field>
|
||||
</record>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Field
|
||||
- Description
|
||||
* - name
|
||||
- Link text
|
||||
* - url
|
||||
- Value of the href attribute
|
||||
* - parent_id
|
||||
- The menu in which the item will be added.
|
||||
* - website_id
|
||||
- The website on which the item will be added.
|
||||
* - sequence
|
||||
- Defines the link's position in the top menu.
|
||||
|
||||
New window
|
||||
----------
|
||||
|
||||
Open the link's URL in a new tab.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<record id="..." model="website.menu">
|
||||
<field name="new_window" eval="True"/>
|
||||
</record>
|
||||
|
||||
External Links
|
||||
--------------
|
||||
|
||||
Add a link to an external website.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<record id="..." model="website.menu">
|
||||
<field name="url">https://www.odoo.com</field>
|
||||
</record>
|
||||
|
||||
Anchor
|
||||
------
|
||||
|
||||
Link to a specific section of a page.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<record id="..." model="website.menu">
|
||||
<field name="url">/about-us#our-team</field>
|
||||
</record>
|
||||
|
||||
Dropdown menu
|
||||
=============
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/menu.xml``
|
||||
|
||||
<record id="menu_services" model="website.menu">
|
||||
<field name="name">Services</field>
|
||||
<field name="website_id">1</field>
|
||||
<field name="parent_id" search="[
|
||||
('url', '=', '/default-main-menu'),
|
||||
('website_id', '=', 1)]"/>
|
||||
<field name="sequence" type="int">...</field>
|
||||
</record>
|
||||
|
||||
Add an item to a dropdown menu.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<record id="menu_services_item_1" model="website.menu">
|
||||
<field name="name">Item 1</field>
|
||||
<field name="url">/dropdown/item-1</field>
|
||||
<field name="website_id">1</field>
|
||||
<field name="parent_id" ref="website_airproof.menu_services"/>
|
||||
<field name="sequence" type="int">...</field>
|
||||
</record>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Field
|
||||
- Description
|
||||
* - parent_id
|
||||
- The dropdown in which the item will be added.
|
||||
|
||||
Mega menu
|
||||
=========
|
||||
|
||||
A mega menu is a dropdown menu with additional possibilities and not just a list of links. In a
|
||||
mega menu, you can use any kind of content (text, images, icons, ...).
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/menu.xml``
|
||||
|
||||
<record id="menu_mega_menu" model="website.menu">
|
||||
<field name="name">Mega Menu</field>
|
||||
<field name="url">/mega-menu</field>
|
||||
<field name="parent_id" search="[
|
||||
('url', '=', '/default-main-menu'),
|
||||
('website_id', '=', 1)]"/>
|
||||
<field name="website_id">1</field>
|
||||
<field name="sequence" type="int">..</field>
|
||||
<field name="is_mega_menu" eval="True"/>
|
||||
<field name="mega_menu_classes">...</field>
|
||||
<field name="mega_menu_content" type="html">
|
||||
<!-- Content -->
|
||||
</field>
|
||||
</record>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Field
|
||||
- Description
|
||||
* - is_mega_menu
|
||||
- Enable the mega menu feature.
|
||||
* - mega_menu_classes
|
||||
- Custom classes to be added to the main element
|
||||
* - mega_menu_content
|
||||
- The default content of the mega menu
|
||||
|
||||
Custom template
|
||||
---------------
|
||||
|
||||
Create your own template and add it to the list.
|
||||
|
||||
**Layout**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/website_templates.xml``
|
||||
|
||||
<template id="s_mega_menu_airproof" name="Airproof" groups="base.group_user">
|
||||
<section class="s_mega_menu_airproof o_cc o_cc1 pt40">
|
||||
<!-- Content -->
|
||||
</section>
|
||||
</template>
|
||||
|
||||
**Option**
|
||||
|
||||
Use the following code to add an option for your new custom mega menu on the Website Builder.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/presets.xml``
|
||||
|
||||
<template id="snippet_options" inherit_id="website.snippet_options" name="Airproof - Mega Menu Options">
|
||||
<xpath expr="//*[@data-name='mega_menu_template_opt']/*" position="before">
|
||||
<t t-set="_label">Airproof</t>
|
||||
<we-button t-att-data-select-label="_label"
|
||||
data-select-template="website_website_airproof.s_mega_menu_airproof"
|
||||
data-img="/website_airproof/static/src/img/builder/header_opt.svg"
|
||||
t-out="_label"/>
|
||||
</xpath>
|
||||
</template>
|
309
content/developer/howtos/website_themes/pages.rst
Normal file
@ -0,0 +1,309 @@
|
||||
=====
|
||||
Pages
|
||||
=====
|
||||
|
||||
In this chapter, you will learn how to declare static pages.
|
||||
|
||||
Default pages
|
||||
=============
|
||||
|
||||
In Odoo, websites come with a few default static pages (Home, Contact us, 404, ...). They are built
|
||||
the following way.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<template id="website.homepage" name="Homepage">
|
||||
<t t-call="website.layout">
|
||||
|
||||
<!-- Variables -->
|
||||
<t t-set="additional_title" t-value="'Home'" />
|
||||
|
||||
<div id="wrap" class="oe_structure oe_empty">
|
||||
|
||||
<!-- Content -->
|
||||
|
||||
</div>
|
||||
|
||||
</t>
|
||||
</template>
|
||||
|
||||
Define the meta title.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-set="additional_title" t-value="'...'"/>
|
||||
|
||||
Define the meta description.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-set="meta_description" t-value="'...'"/>
|
||||
|
||||
Add a CSS class to the page.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-set="pageName" t-value="'...'"/>
|
||||
|
||||
Hide the header.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-set="no_header" t-value="true"/>
|
||||
|
||||
Hide the footer.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-set="no_footer" t-value="true"/>
|
||||
|
||||
If needed, deactivate default pages.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/pages/home.xml``
|
||||
|
||||
<record id="website.homepage" model="ir.ui.view">
|
||||
<field name="active" eval="False"/>
|
||||
</record>
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/pages/contactus.xml``
|
||||
|
||||
<record id="website.contactus" model="ir.ui.view">
|
||||
<field name="active" eval="False"/>
|
||||
</record>
|
||||
|
||||
Alternatively, replace the default content of these pages using XPath.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/pages/404.xml``
|
||||
|
||||
<template id="404" inherit_id="http_routing.404">
|
||||
<xpath expr="//*[@id='wrap']" position="replace">
|
||||
|
||||
<t t-set="additional_title" t-value="'404 - Not found'"/>
|
||||
|
||||
<div id="wrap" class="oe_structure">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
.. seealso::
|
||||
- `Odoo eLearning: Search Engine Optimization (SEO)
|
||||
<https://www.odoo.com/slides/slide/search-engine-optimization-seo-648>`_
|
||||
- :doc:`Odoo Documentation on SEO <../../../applications/websites/website/pages/seo>`
|
||||
|
||||
Theme pages
|
||||
===========
|
||||
|
||||
You can add as many pages as you want to your website. Instead of defining a `<template>`, create a
|
||||
page object.
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/pages/about_us.xml``
|
||||
|
||||
<record id="page_about_us" model="website.page">
|
||||
<field name="name">About us</field>
|
||||
<field name="is_published" eval="True"/>
|
||||
<field name="key">website_airproof.page_about_us</field>
|
||||
<field name="url">/about-us</field>
|
||||
<field name="type">qweb</field>
|
||||
<field name="arch" type="xml">
|
||||
<t t-name="website_airproof.page_about_us">
|
||||
|
||||
<t t-call="website.layout">
|
||||
<div id="wrap" class="oe_structure">
|
||||
|
||||
<!-- Content -->
|
||||
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</t>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
.. todo:: Missing description in table ...
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Field
|
||||
- Description
|
||||
* - name
|
||||
- Page name.
|
||||
* - is_published
|
||||
- Define if the page is published (visible to visitors).
|
||||
* - key
|
||||
- View key (must be unique)
|
||||
* - url
|
||||
- URL where the page is reachable.
|
||||
* - type
|
||||
- View type
|
||||
* - arch
|
||||
- View architecture
|
||||
|
||||
With `<t t-call="website.layout">` you use the Odoo default page layout with your code.
|
||||
|
||||
.. _header_overlay:
|
||||
|
||||
Header overlay
|
||||
--------------
|
||||
|
||||
Make the header background transparent and stand on top of the page content.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<field name="header_overlay" eval="True"/>
|
||||
|
||||
.. image:: pages/header-overlay.png
|
||||
:alt: Header overlay
|
||||
|
||||
Media
|
||||
=====
|
||||
|
||||
Images
|
||||
------
|
||||
|
||||
You can record images in the database and use them later in your design/code. They will also be
|
||||
available for the end user through the *media dialog*.
|
||||
|
||||
.. image:: pages/media-window.png
|
||||
:alt: Media window
|
||||
|
||||
The Website Builder supports the following image file formats: JPG, GIF, PNG, and SVG.
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/images.xml``
|
||||
|
||||
<record id="img_about_01" model="ir.attachment">
|
||||
<field name="name">About Image 01</field>
|
||||
<field name="datas" type="base64" file="website_airproof/static/src/img/content/img_about_01.jpg"/>
|
||||
<field name="res_model">ir.ui.view</field>
|
||||
<field name="public" eval="True"/>
|
||||
</record>
|
||||
|
||||
.. todo:: Missing description in table ...
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Field
|
||||
- Description
|
||||
* - name
|
||||
- Image name
|
||||
* - datas
|
||||
- Path to the image file
|
||||
* - res_model
|
||||
- Name of the wizard model
|
||||
|
||||
Use it as a background image.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section style="background-image: url('/web/image/website_airproof.img_about_01');">
|
||||
|
||||
Use it as a regular image.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<img src="/web/image/website_airproof.img_about_01" alt=""/>
|
||||
|
||||
Use as a regular image with a color filter.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<img src="/web/image/website.s_media_list_default_image_1"
|
||||
class="img img-fluid mx-auto" alt=""
|
||||
data-gl-filter="custom"
|
||||
data-filter-options="{'filterColor': 'rgba(0, 0, 0, 0.5)'}"/>
|
||||
|
||||
.. tip::
|
||||
The image size greatly influences the user experience, search engine optimization, and overall
|
||||
website performance. So, be sure to size your images correctly.
|
||||
|
||||
Videos
|
||||
------
|
||||
|
||||
Add videos as background.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section class="o_background_video" data-bg-video-src="...">
|
||||
<!-- Content -->
|
||||
</section>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - data-bg-video-src
|
||||
- Video URL.
|
||||
|
||||
Add videos as content.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<div class="media_iframe_video" data-oe-expression="...">
|
||||
<div class="css_editable_mode_display"> </div>
|
||||
<div class="media_iframe_video_size" contenteditable="false"> </div>
|
||||
<iframe src="..."
|
||||
frameborder="0"
|
||||
contenteditable="false"
|
||||
allowfullscreen="allowfullscreen"/>
|
||||
</div>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - data-oe-expression
|
||||
- Video URL.
|
||||
* - src
|
||||
- Video URL.
|
||||
|
||||
Icons
|
||||
-----
|
||||
|
||||
By default, the Font Awesome icons library is included in the Website Builder. You can place icons
|
||||
anywhere using the CSS Prefix `fa` and the icon's name. Font Awesome is designed to be used with
|
||||
inline elements. You can use `<i>` tag for brevity, but using a `<span>` is more semantically
|
||||
correct.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<span class="fa fa-picture-o"/>
|
||||
|
||||
.. seealso::
|
||||
`Font Awesome v4 icons <https://fontawesome.com/v4/icons/>`_
|
||||
|
||||
Enable the Website Builder style options.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<span class="fa fa-2x fa-picture-o rounded-circle"/>
|
||||
|
||||
Increase the icon size (fa-2x, fa-3x, fa-4x, or fa-5x classes).
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<span class="fa fa-2x fa-picture-o"/>
|
||||
|
||||
.. image:: pages/icon-options.png
|
||||
:alt: Icon options
|
BIN
content/developer/howtos/website_themes/pages/header-overlay.png
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
content/developer/howtos/website_themes/pages/icon-options.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
content/developer/howtos/website_themes/pages/media-window.png
Normal file
After Width: | Height: | Size: 100 KiB |
256
content/developer/howtos/website_themes/setup.rst
Normal file
@ -0,0 +1,256 @@
|
||||
=====
|
||||
Setup
|
||||
=====
|
||||
|
||||
In this chapter, you will learn:
|
||||
|
||||
- To set up your local development environment.
|
||||
- The outline of the Odoo database structure.
|
||||
- To export and import an Odoo database in your local environment.
|
||||
- To have an Odoo instance up and running.
|
||||
|
||||
Install
|
||||
=======
|
||||
|
||||
There are multiple ways to :doc:`install Odoo <../../../administration/install/install>`, depending on the intended use case. This documentation
|
||||
assumes you use the :ref:`source install <setup/install/source>` (running Odoo from the source code), which is best suited
|
||||
for Odoo designers and developers.
|
||||
|
||||
Databases
|
||||
=========
|
||||
|
||||
Structure
|
||||
---------
|
||||
|
||||
Every Odoo application works similarly; they are built with the same logic. A model contains fields
|
||||
and relational fields that link to other models. Each model has views representing all its fields,
|
||||
with backend and frontend views.
|
||||
|
||||
Models
|
||||
~~~~~~
|
||||
|
||||
The basis of Odoo is models. Models use fields to record the data. Records are stored in a database:
|
||||
they are therefore linked to a model. In Odoo, you can find the different models in the
|
||||
backend by enabling the :ref:`developer mode <developer-mode>` and then going to
|
||||
:menuselection:`Settings --> Technical --> Database Structure: Models`.
|
||||
|
||||
.. image:: setup/models-page.png
|
||||
:alt: Models page
|
||||
|
||||
Fields
|
||||
~~~~~~
|
||||
|
||||
In a model, we will centralize fields (field names we need to target in our code).
|
||||
|
||||
.. seealso::
|
||||
:doc:`/applications/productivity/studio/fields`
|
||||
|
||||
Classic fields
|
||||
**************
|
||||
|
||||
- Date
|
||||
- Char
|
||||
- Selection
|
||||
- …
|
||||
|
||||
Relational fields
|
||||
*****************
|
||||
|
||||
Relational fields call a field from another model. They allow you to link models together and make
|
||||
them interact easily. In other words, when you use a relational field, you link a record with
|
||||
another one (located on another model), enabling you to retrieve the content of the fields located
|
||||
on this linked record.
|
||||
|
||||
- **Many2one** fields are filled in by choosing one record from a list of records on another model
|
||||
(from *many* records, you select *one*). For example, the *customer* field on a quotation makes
|
||||
you choose one customer from a list of several customers on the *contact* model.
|
||||
- **One2many** fields are reverse searches of existing many2one relations. For example, you could
|
||||
list on a contact all their existing quotations (from *one* record, you display *many*).
|
||||
- **Many2many** fields are filled in by choosing one or several records from a list of records on
|
||||
another model. For example, you can put several tags on one product, and several products can use
|
||||
the same tags (from *many* records, you can select *many*).
|
||||
|
||||
Views
|
||||
~~~~~
|
||||
|
||||
Views define how records should be displayed to end-users. They are specified in XML, meaning they
|
||||
can be edited independently from the models they represent. They are flexible and allow deep
|
||||
customization of the screens they control.
|
||||
|
||||
Backend vs. Frontend
|
||||
********************
|
||||
|
||||
- **Backend views**: Kanban, List, Form, etc.
|
||||
- **Frontend view**: QWeb
|
||||
|
||||
Static vs. Dynamic
|
||||
******************
|
||||
|
||||
- **Static pages** have stable content, such as the homepage. You can define their URL and set some
|
||||
properties like published, indexed, etc.
|
||||
- **Dynamic pages** are dynamically generated, such as the product page. Their URL is dynamic
|
||||
and is accessible to all by default (this can be changed by configuring access rights).
|
||||
|
||||
Standard vs. Inherited
|
||||
**********************
|
||||
|
||||
- **Standard views** are base views implemented by Odoo. They are directly derived from their model.
|
||||
You should never change them as they allow updating an Odoo database without overwriting a
|
||||
client's modifications.
|
||||
- **Inherited views** are duplicated views. Modifications always take place in an inherited view. If
|
||||
there is a duplicate view, there will be two views with the same name in the database, but the
|
||||
duplicated view will not have an ID like for standard view.
|
||||
|
||||
Import an existing database
|
||||
---------------------------
|
||||
|
||||
.. note::
|
||||
You can directly go to the :doc:`theming` chapter if you do not need to import an existing
|
||||
database.
|
||||
|
||||
Dump
|
||||
~~~~
|
||||
|
||||
Odoo SaaS
|
||||
*********
|
||||
|
||||
Go to `<database_url>/saas_worker/dump`.
|
||||
|
||||
Odoo.sh
|
||||
*******
|
||||
|
||||
#. Connect to Odoo.sh.
|
||||
#. Select the branch you want to back up.
|
||||
#. Choose the :guilabel:`BACKUPS` tab.
|
||||
#. Click the :guilabel:`Create Backup` button.
|
||||
#. When the process is over, a notification appears. Open it and click the :guilabel:`Go to Backup`
|
||||
button.
|
||||
#. Click the :guilabel:`Download` icon. Select :guilabel:`Testing` under
|
||||
:guilabel:`Purpose` and :guilabel:`With filestore` under :guilabel:`Filestore`.
|
||||
|
||||
.. image:: setup/download-backup.png
|
||||
:alt: Download backup
|
||||
|
||||
#. You will receive a notification when the dump is ready to be downloaded. Open it and click on
|
||||
:guilabel:`Download` to get your dump.
|
||||
|
||||
.. image:: setup/database-backup.png
|
||||
:alt: Database backup
|
||||
|
||||
Move filestore
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Copy all the folders included in the filestore folder and paste them to the following location on
|
||||
your computer:
|
||||
|
||||
- macOS: `/Users/<User>/Library/Application Support/Odoo/filestore/<database_name>`
|
||||
- Linux: `/home/<User>/.local/share/Odoo/filestore/<database_name>`
|
||||
|
||||
.. note::
|
||||
`/Library` is a hidden folder.
|
||||
|
||||
Database setup
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Create an empty database.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
createdb <database_name>
|
||||
|
||||
Import the SQL file in the database that you just created.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
psql <database_name> < dump.sql
|
||||
|
||||
Reset the admin user password.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
psql \c
|
||||
<database_name>
|
||||
update res_users set login='admin', password='admin' where id=2;
|
||||
|
||||
Getting started
|
||||
===============
|
||||
|
||||
Running Odoo
|
||||
------------
|
||||
|
||||
Once all dependencies are set up, Odoo can be launched by running `odoo-bin`, the command-line
|
||||
interface of the server. It is located at the root of the Odoo Community directory.
|
||||
|
||||
- :ref:`Running Odoo <setup/install/source/running_odoo>`
|
||||
- `Docker <https://hub.docker.com/_/odoo/>`_
|
||||
|
||||
To configure the server, you can specify command-line arguments or a configuration file. The first
|
||||
method is presented below.
|
||||
|
||||
The :ref:`CLI <reference/cmdline>` offers several functionalities related to Odoo. You can use it to
|
||||
:ref:`run the server <reference/cmdline/server>`, scaffold an Odoo theme, populate a database, or
|
||||
count the number of lines of code.
|
||||
|
||||
Shell script
|
||||
------------
|
||||
|
||||
A typical way to :ref:`run the server <reference/cmdline/server>` would be to add all command line arguments to a `.sh` script.
|
||||
|
||||
.. example::
|
||||
.. code-block:: xml
|
||||
|
||||
./odoo-bin --addons-path=../enterprise,addons --db-filter=<database> -d <database> --without-demo=all -i website --dev=xml
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Folder
|
||||
- Description
|
||||
* - :option:`--addons-path <odoo-bin --addons-path>`
|
||||
- Comma-separated list of directories in which modules are stored. These directories are
|
||||
scanned for modules.
|
||||
* - :option:`-d <odoo-bin --database>`
|
||||
|
||||
:option:`--database <odoo-bin --database>`
|
||||
- database(s) used when installing or updating modules.
|
||||
* - :option:`--db-filter <odoo-bin --db-filter>`
|
||||
- Hides databases that do not match the filter.
|
||||
* - :option:`-i <odoo-bin --init>`
|
||||
|
||||
:option:`--init <odoo-bin --init>`
|
||||
- Comma-separated list of modules to install before running the server. (requires `-d`)
|
||||
* - :option:`-u <odoo-bin --update>`
|
||||
|
||||
:option:`--update <odoo-bin --update>`
|
||||
- Comma-separated list of modules to update before running the server. (requires `-d`)
|
||||
* - :option:`--without-demo <odoo-bin --without-demo>`
|
||||
- Disables demo data loading for modules installed comma-separated; use `all` for all modules.
|
||||
(requires `-d` and `-i`)
|
||||
* - :option:`--dev <odoo-bin --dev>`
|
||||
- Comma-separated list of features. For development purposes only. :ref:`More info
|
||||
<reference/cmdline/dev>`
|
||||
|
||||
Sign in
|
||||
-------
|
||||
|
||||
After the server has started (the INFO log `odoo.modules.loading: Modules loaded.` is printed), open
|
||||
http://localhost:8069 in your web browser and log in with the base administrator account.
|
||||
|
||||
Type **admin** for the email and **admin** for the password.
|
||||
|
||||
.. image:: setup/welcome-homepage.png
|
||||
:alt: Welcome homepage
|
||||
|
||||
.. tip::
|
||||
Hit *CTRL+C* to stop the server. Do it twice if needed.
|
||||
|
||||
Developer mode
|
||||
--------------
|
||||
|
||||
The developer mode, also known as debug mode, is useful for development as it gives access to
|
||||
additional tools. In the next chapters, it is assumed that you have enabled the developer mode.
|
||||
|
||||
.. seealso::
|
||||
:doc:`/applications/general/developer_mode`
|
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 12 KiB |
BIN
content/developer/howtos/website_themes/setup/models-page.png
Normal file
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 26 KiB |
233
content/developer/howtos/website_themes/shapes.rst
Normal file
@ -0,0 +1,233 @@
|
||||
======
|
||||
Shapes
|
||||
======
|
||||
|
||||
Shapes are handy if you want to add personality to your website.
|
||||
|
||||
In this chapter, you will learn how to add standard and custom background and image shapes.
|
||||
|
||||
Background shapes
|
||||
=================
|
||||
|
||||
Background shapes are SVG files that you can add as a decorative background in your different
|
||||
sections. Each shape has one or several customizable colors, and some of them are animated.
|
||||
|
||||
Standard
|
||||
--------
|
||||
|
||||
A large selection of default background shapes is available.
|
||||
|
||||
**Use**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section data-oe-shape-data="{'shape':'web_editor/Zigs/06'}">
|
||||
<div class="o_we_shape o_web_editor_Zigs_06"/>
|
||||
<div class="container">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
`data-oe-shape-data` is the location of your shape.
|
||||
|
||||
Flip the shape horizontally or vertically by using the X or Y axis.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section data-oe-shape-data="{'shape':'web_editor/Zigs/06','flip':[x,y]}">
|
||||
<div class="o_we_shape o_we_flip_x o_we_flip_y o_web_editor_Zigs_06"/>
|
||||
<div class="container">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Colors mapping
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
You can also change the default color mapping of your shape.
|
||||
|
||||
Switch colors mapping
|
||||
*********************
|
||||
|
||||
First, put the c* color (here `4`).
|
||||
|
||||
Then, the replacement color (here `3`). These replacement colors also range from 1 to 5:
|
||||
|
||||
- `1` = background color of the color preset 1 (o-cc1).
|
||||
- `2` = background color of the color preset 2 (o-cc2).
|
||||
- `3` = background color of the color preset 3 (o-cc3).
|
||||
- `4` = background color of the color preset 4 (o-cc4).
|
||||
- `5` = background color of the color preset 5 (o-cc5).
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/boostrap_overridden.scss``
|
||||
|
||||
$o-bg-shapes: change-shape-colors-mapping('web_editor', 'Zigs/06', (4: 3, 5: 1));
|
||||
|
||||
Add extra colors mapping
|
||||
************************
|
||||
|
||||
Adding extra color mapping allows you to add a color variant to the template of a shape while
|
||||
keeping the original.
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/boostrap_overridden.scss``
|
||||
|
||||
$o-bg-shapes: add-extra-shape-colors-mapping('web_editor', 'Zigs/06', 'second', (4: 3, 5: 1));
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<section data-oe-shape-data="{'shape':'web_editor/Zigs/06'}">
|
||||
<div class="o_we_shape o_web_editor_Zigs_06 o_second_extra_shape_mapping"/>
|
||||
<div class="container">
|
||||
<!-- Content -->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Custom
|
||||
------
|
||||
|
||||
Sometimes, your design might require creating one or several custom shapes.
|
||||
|
||||
Firstly, you need to create an SVG file for your shape.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/static/shapes/hexagons/01.svg``
|
||||
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="86" height="100">
|
||||
<polygon points="0 25, 43 0, 86 25, 86 75, 43 100, 0 75" style="fill: #3AADAA;"/>
|
||||
</svg>
|
||||
|
||||
Make sure to use colors from the default Odoo palette for your shape.
|
||||
|
||||
.. code-block:: scss
|
||||
|
||||
default_palette = {
|
||||
'1': '#3AADAA',
|
||||
'2': '#7C6576',
|
||||
'3': '#F6F6F6',
|
||||
'4': '#FFFFFF',
|
||||
'5': '#383E45',
|
||||
}
|
||||
|
||||
Declare your shape file.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/shapes.xml``
|
||||
|
||||
<record id="shape_hexagon_01" model="ir.attachment">
|
||||
<field name="name">01.svg</field>
|
||||
<field name="datas" type="base64" file="website_airproof/static/shapes/hexagons/01.svg"/>
|
||||
<field name="url">/web_editor/shape/illustration/hexagons/01.svg</field>
|
||||
<field name="public" eval="True"/>
|
||||
</record>
|
||||
|
||||
.. todo:: Missing description in table ...
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Field
|
||||
- Description
|
||||
* - name
|
||||
- Name of the shape
|
||||
* - datas
|
||||
- Path to the shape
|
||||
* - url
|
||||
- ...
|
||||
* - public
|
||||
- Makes the shape available for later editing.
|
||||
|
||||
Define the styles of your shape.
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-bg-shapes: map-merge($o-bg-shapes,
|
||||
(
|
||||
'illustration': map-merge(
|
||||
map-get($o-bg-shapes, 'illustration') or (),
|
||||
(
|
||||
'hexagons/01': ('position': center center, 'size': auto 100%, 'colors': (1), 'repeat-x': true, 'repeat-y': true),
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Key
|
||||
- Description
|
||||
* - File location
|
||||
- `hexagons/01` corresponds to the location of your file in the `shapes` folder.
|
||||
* - position
|
||||
- Defines the position of your shape.
|
||||
* - size
|
||||
- Defines the size of your shape.
|
||||
* - colors
|
||||
- Defines the color c* you want it to have (this will override the color you specified in your
|
||||
SVG).
|
||||
* - repeat-x
|
||||
- Defines if the shape is repeated horizontally. This key is optional and only needs to be
|
||||
defined if set to `true`.
|
||||
* - repeat-y
|
||||
- Defines if the shape is repeated vertically. This key is optional and only needs to be
|
||||
defined if set to `true`.
|
||||
|
||||
Lastly, add your shape to the list of shapes available on the Website Builder.
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/views/snippets/options.xml``
|
||||
|
||||
<template id="snippet_options_background_options" inherit_id="website.snippet_options_background_options" name="Shapes">
|
||||
<xpath expr="//*[hasclass('o_we_shape_menu')]/*[last()]" position="after">
|
||||
<we-select-page string="Theme">
|
||||
<we-button data-shape="illustration/hexagons/01" data-select-label="Hexagon 01"/>
|
||||
</we-select-page>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
Your custom shape can now be used the same way as standard shapes.
|
||||
|
||||
Image shapes
|
||||
============
|
||||
|
||||
Image shapes are SVG files you can add as a clipping mask on your images. Some shapes have
|
||||
customizable colors, and some are animated.
|
||||
|
||||
Standard
|
||||
--------
|
||||
|
||||
A large selection of default image shapes is available.
|
||||
|
||||
**Use**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<img src="..."
|
||||
class="img img-fluid mx-auto"
|
||||
alt="..."
|
||||
data-shape="web_editor/solid/blob_2_solid_str"
|
||||
data-shape-colors="#35979C;;;;"
|
||||
>
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Attribute
|
||||
- Description
|
||||
* - data-shape
|
||||
- Location of the shape
|
||||
* - data-shape-colors
|
||||
- Colors applied to the shape
|
||||
|
||||
.. warning::
|
||||
Sometimes, your image shape might not be applied after adding your changes. To fix the issue,
|
||||
open the Website Builder and save the page to force the shape to load.
|
637
content/developer/howtos/website_themes/theming.rst
Normal file
@ -0,0 +1,637 @@
|
||||
=======
|
||||
Theming
|
||||
=======
|
||||
|
||||
After your development environment is fully set up, you can start building the skeleton of your
|
||||
theme module. In this chapter, you will discover how to:
|
||||
|
||||
- Enable/disable the Website Builder's standard options and templates.
|
||||
- Define the colors and fonts to use for your design.
|
||||
- Get the most out of Bootstrap variables.
|
||||
- Add custom styles and JavaScript.
|
||||
|
||||
Theme module
|
||||
============
|
||||
|
||||
Odoo comes with a default theme that provides minimal structure and layout. When you create a new
|
||||
theme, you are extending the default theme.
|
||||
|
||||
Remember to add the directory containing your module to the `addons-path` command-line argument
|
||||
when running Odoo in your development environment.
|
||||
|
||||
Technical naming
|
||||
----------------
|
||||
|
||||
The first step is to create a new directory.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
website_airproof
|
||||
|
||||
.. note::
|
||||
Prefix it with `website_` and use only lowercase ASCII alphanumeric characters and underscores.
|
||||
|
||||
In this documentation, we will use **Airproof** (a fictional project) as an example.
|
||||
|
||||
File structure
|
||||
--------------
|
||||
|
||||
Themes are packaged like any Odoo module. Even if you are designing a basic website, you need to
|
||||
package its theme like a module.
|
||||
|
||||
::
|
||||
|
||||
website_airproof
|
||||
├── data
|
||||
├── i18n
|
||||
├── lib
|
||||
├── static
|
||||
│ ├── description
|
||||
│ ├── fonts
|
||||
│ ├── image_shapes // Shapes for images
|
||||
│ ├── shapes // Shapes for background
|
||||
│ └── src
|
||||
│ ├── img
|
||||
│ │ ├── content // For those used in the pages of your website
|
||||
│ │ └── wbuilder // For those used in the builder
|
||||
│ ├── js
|
||||
│ ├── scss
|
||||
│ └── snippets // custom snippets
|
||||
├── views
|
||||
├── __init__.py
|
||||
└── __manifest__.py
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Folder
|
||||
- Description
|
||||
* - data
|
||||
- Presets, menus, pages, images, shapes, … (`*.xml`)
|
||||
* - i18n
|
||||
- Translations (`*.po`, `*.pot`)
|
||||
* - lib
|
||||
- External libraries (`*.js`)
|
||||
* - static
|
||||
- Custom assets (`*.jpg`, `*.gif`, `*.png`, `*.svg`, `*.pdf`, `*.scss`, `*.js`)
|
||||
* - views
|
||||
- Custom views and templates (`*.xml`)
|
||||
|
||||
Initialization
|
||||
--------------
|
||||
|
||||
An Odoo module is also a Python package with a :file:`__init__.py` file containing import
|
||||
instructions for various Python files in the module. This file can remain empty for now.
|
||||
|
||||
Declaration
|
||||
-----------
|
||||
|
||||
An Odoo module is declared by its manifest file. This file declares a Python package as an Odoo
|
||||
module and specifies the module's metadata. It must at least contain the `name` field, which is
|
||||
always required. It usually contains much more information.
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``/website_airproof/__manifest__.py``
|
||||
|
||||
{
|
||||
'name': 'Airproof Theme',
|
||||
'description': '...',
|
||||
'category': 'Website/Theme',
|
||||
'version': '15.0.0',
|
||||
'author': '...',
|
||||
'license': '...',
|
||||
'depends': ['website'],
|
||||
'data': [
|
||||
# ...
|
||||
],
|
||||
'assets': {
|
||||
# ...
|
||||
},
|
||||
}
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Field
|
||||
- Description
|
||||
* - name
|
||||
- Human-readable name of the module (required)
|
||||
* - description
|
||||
- Extended description of the module, in `reStructuredText
|
||||
<https://en.wikipedia.org/wiki/ReStructuredText>`_
|
||||
* - category
|
||||
- Classification category within Odoo
|
||||
* - version
|
||||
- Odoo version this module is addressing
|
||||
* - author
|
||||
- Name of the module author
|
||||
* - license
|
||||
- Distribution license for the module
|
||||
* - depends
|
||||
- Odoo modules must be loaded before this one, either because this module uses features
|
||||
they create or because it alters resources they define
|
||||
* - data
|
||||
- List of XML files
|
||||
* - assets
|
||||
- List of SCSS and JS files
|
||||
|
||||
.. note::
|
||||
To create a website theme, you only need to install the Website app. If you need other apps
|
||||
(Blogs, Events, eCommerce, ...), you can also add them.
|
||||
|
||||
Default options
|
||||
===============
|
||||
|
||||
First, try to construct your theme by using Odoo's default options. This ensures two things:
|
||||
|
||||
#. You do not re-invent something which already exists. For example, as Odoo provides an option to
|
||||
add a border on the footer, you shouldn't recode it yourself. Instead, enable the default option
|
||||
first, then extend it if needed.
|
||||
#. The user can still use all of Odoo's features with your theme. For example, if you recode the
|
||||
border on the footer, you may break the default option or make it useless, giving the user a bad
|
||||
experience. Also, your recode might not work as well as the default option, as other Odoo
|
||||
features may rely on it.
|
||||
|
||||
.. tip::
|
||||
- Use four spaces per indentation level.
|
||||
- Do not use tabs.
|
||||
- Never mix spaces and tabs.
|
||||
|
||||
.. seealso::
|
||||
:doc:`Odoo coding guidelines <../../../contributing/development/coding_guidelines>`
|
||||
|
||||
Odoo variables
|
||||
--------------
|
||||
|
||||
Odoo declares many CSS rules, most entirely customizable by overriding the related SCSS variables.
|
||||
To do so, create a :file:`primary_variables.scss` file and add it to the `_assets_primary_variables`
|
||||
bundle.
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``/website_airproof/__manifest__.py``
|
||||
|
||||
'assets': {
|
||||
'web._assets_primary_variables': [
|
||||
('prepend', 'website_airproof/static/src/scss/primary_variables.scss'),
|
||||
],
|
||||
},
|
||||
|
||||
By reading the source code, variables related to options are easily noticeable.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<we-button title="..."
|
||||
data-name="..."
|
||||
data-customize-website-views="..."
|
||||
data-customize-website-variable="'Sidebar'"
|
||||
data-img="..."/>
|
||||
|
||||
These variables can be overridden through the `$o-website-value-palettes` map, for example.
|
||||
|
||||
Global
|
||||
~~~~~~
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-website-values-palettes: (
|
||||
(
|
||||
// Templates
|
||||
// Colors
|
||||
// Fonts
|
||||
// Buttons
|
||||
// ...
|
||||
),
|
||||
);
|
||||
|
||||
.. tip::
|
||||
That file must only contain definitions and overrides of SCSS variables and mixins.
|
||||
|
||||
.. seealso::
|
||||
`Primary variables SCSS
|
||||
<https://github.com/odoo/odoo/blob/34c0c9c1ae00aba391932129d4cefd027a9c6bbd/addons/website/static/src/scss/primary_variables.scss#L1954>`_
|
||||
|
||||
Fonts
|
||||
~~~~~
|
||||
|
||||
You can embed any font on your website. The Website Builder automatically makes them available in
|
||||
the font selector.
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-theme-font-configs: (
|
||||
<font-name>: (
|
||||
'family': <css font family list>,
|
||||
'url' (optional): <related part of Google fonts URL>,
|
||||
'properties' (optional): (
|
||||
<font-alias>: (
|
||||
<website-value-key>: <value>,
|
||||
...,
|
||||
),
|
||||
...,
|
||||
)
|
||||
)
|
||||
|
||||
**Use**
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-website-values-palettes: (
|
||||
(
|
||||
'font': '<font-name>',
|
||||
'headings-font': '<font-name>',
|
||||
'navbar-font': '<font-name>',
|
||||
'buttons-font': '<font-name>',
|
||||
),
|
||||
);
|
||||
|
||||
Google fonts
|
||||
************
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-theme-font-configs: (
|
||||
'Poppins': (
|
||||
'family': ('Poppins', sans-serif),
|
||||
'url': 'Poppins:400,500',
|
||||
'properties' : (
|
||||
'base': (
|
||||
'font-size-base': 1rem,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Custom fonts
|
||||
************
|
||||
|
||||
First, create a specific SCSS file to declare your custom font(s).
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``/website_airproof/__manifest__.py``
|
||||
|
||||
'assets': {
|
||||
'web.assets_frontend': [
|
||||
'website_airproof/static/src/scss/font.scss',
|
||||
],
|
||||
},
|
||||
|
||||
Then, use the `@font-face` rule to allow you custom font(s) to be loaded on your website.
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/font.scss``
|
||||
|
||||
@font-face {
|
||||
font-family: '<font-name>';
|
||||
...
|
||||
}
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-theme-font-configs: (
|
||||
'Proxima Nova': (
|
||||
'family': ('Proxima Nova', sans-serif),
|
||||
'properties' : (
|
||||
'base': (
|
||||
'font-size-base': 1rem,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
.. tip::
|
||||
It is recommended to use the .woff format for your fonts.
|
||||
|
||||
Colors
|
||||
~~~~~~
|
||||
|
||||
The Website Builder relies on palettes composed of five named colors. Defining those in your theme
|
||||
ensures it stays consistent.
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
:stub-columns: 1
|
||||
:widths: 20 80
|
||||
|
||||
* - Color
|
||||
- Description
|
||||
* - o-color-1
|
||||
- Primary
|
||||
* - o-color-2
|
||||
- Secondary
|
||||
* - o-color-3
|
||||
- Extra
|
||||
* - o-color-4
|
||||
- Whitish
|
||||
* - o-color-5
|
||||
- Blackish
|
||||
|
||||
.. image:: theming/theme-colors.png
|
||||
:alt: Theme colors
|
||||
:width: 300
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-color-palettes: map-merge($o-color-palettes,
|
||||
(
|
||||
'airproof': (
|
||||
'o-color-1': #bedb39,
|
||||
'o-color-2': #2c3e50,
|
||||
'o-color-3': #f2f2f2,
|
||||
'o-color-4': #ffffff,
|
||||
'o-color-5': #000000,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
Add the created palette to the list of palettes offered by the Website Builder.
|
||||
|
||||
.. code-block:: scss
|
||||
|
||||
$o-selected-color-palettes-names: append($o-selected-color-palettes-names, 'airproof');
|
||||
|
||||
**Use**
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-website-values-palettes: (
|
||||
(
|
||||
'color-palettes-name': 'airproof',
|
||||
),
|
||||
);
|
||||
|
||||
.. image:: theming/theme-colors-airproof.png
|
||||
:alt: Theme colors Airproof
|
||||
:width: 800
|
||||
|
||||
**Color combinations**
|
||||
|
||||
Based on the previously defined five color palettes, the Website Builder automatically generates
|
||||
five color combinations, each defining a color for the background, text, headings, links, primary
|
||||
buttons, and secondary buttons. These colors can be customized later by the user.
|
||||
|
||||
.. image:: theming/theme-colors-big.png
|
||||
:alt: Theme colors
|
||||
:width: 300
|
||||
|
||||
The colors used in a color combination are accessible and can be overridden through the BS
|
||||
`$colors map` using a specific prefix (`o-cc` for `color combination`).
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/primary_variables.scss``
|
||||
|
||||
$o-color-palettes: map-merge($o-color-palettes,
|
||||
(
|
||||
'airproof': (
|
||||
|
||||
'o-cc*-bg': 'o-color-*',
|
||||
'o-cc*-text': 'o-color-*',
|
||||
'o-cc*-headings': 'o-color-*',
|
||||
'o-cc*-h2': 'o-color-*',
|
||||
'o-cc*-h3': 'o-color-*',
|
||||
'o-cc*-h4': 'o-color-*',
|
||||
'o-cc*-h5': 'o-color-*',
|
||||
'o-cc*-h6': 'o-color-*',
|
||||
'o-cc*-link': 'o-color-*',
|
||||
'o-cc*-btn-primary': 'o-color-*',
|
||||
'o-cc*-btn-primary-border': 'o-color-*',
|
||||
'o-cc*-btn-secondary': 'o-color-*',
|
||||
'o-cc*-btn-secondary-border': 'o-color-*',
|
||||
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
.. note::
|
||||
For each `o-cc*`, replace the `*` with the digit (1 - 5) corresponding to the desired color
|
||||
combination.
|
||||
|
||||
The default text color is `o-color-5`. If the background is too dark, it will automatically
|
||||
change to the `o-color-4` color.
|
||||
|
||||
.. seealso::
|
||||
`Color combinations SCSS
|
||||
<https://github.com/odoo/odoo/blob/34c0c9c1ae00aba391932129d4cefd027a9c6bbd/addons/web_editor/static/src/scss/web_editor.common.scss#L711>`_
|
||||
|
||||
.. admonition:: Demo page
|
||||
|
||||
The Website Builder automatically generates a page to view the color combinations of the theme
|
||||
color palette: http://localhost:8069/website/demo/color-combinations
|
||||
|
||||
Bootstrap variables
|
||||
-------------------
|
||||
|
||||
Odoo includes Bootstrap by default. You can use all variables and mixins of the framework.
|
||||
|
||||
If Odoo does not provide the variable you are looking for, there could be a Bootstrap variable that
|
||||
allows it. Indeed all Odoo layouts respect Bootstrap structures and use Bootstrap components or
|
||||
their extensions. If you customize a Bootstrap variable, you add a generic style for the whole user
|
||||
website.
|
||||
|
||||
Use a dedicated file added to the :file:`_assets_frontend_helpers` bundle to override Bootstrap
|
||||
values and *not* the :file:`primary_variables.scss` file.
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``/website_airproof/__manifest__.py``
|
||||
|
||||
'assets': {
|
||||
'web._assets_frontend_helpers': [
|
||||
('prepend', 'website_airproof/static/src/scss/bootstrap_overridden.scss'),
|
||||
],
|
||||
},
|
||||
|
||||
**Use**
|
||||
|
||||
.. code-block:: scss
|
||||
:caption: ``/website_airproof/static/src/scss/bootstrap_overridden.scss``
|
||||
|
||||
// Typography
|
||||
$h1-font-size: 4rem !default;
|
||||
|
||||
// Navbar
|
||||
$navbar-nav-link-padding-x: 1rem!default;
|
||||
|
||||
// Buttons + Forms
|
||||
$input-placeholder-color: o-color('o-color-1') !default;
|
||||
|
||||
// Cards
|
||||
$card-border-width: 0 !default;
|
||||
|
||||
.. tip::
|
||||
That file must only contain definitions and overrides of SCSS variables and mixins.
|
||||
|
||||
.. warning::
|
||||
Don't override Bootstrap variables that depend on Odoo variables. Otherwise, you might break the
|
||||
possibility for the user to customize them using the Website Builder.
|
||||
|
||||
.. seealso::
|
||||
`Bootstrap overridden SCSS
|
||||
<{GITHUB_PATH}/addons/website/static/src/scss/bootstrap_overridden.scss>`_
|
||||
|
||||
.. admonition:: Demo page
|
||||
|
||||
http://localhost:8069/website/demo/bootstrap
|
||||
|
||||
Views
|
||||
-----
|
||||
|
||||
For some options, in addition to the Website Builder variable, you also have to activate a specific
|
||||
view.
|
||||
|
||||
By reading the source code, templates related to options are easily found.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<we-button title="..."
|
||||
data-name="..."
|
||||
data-customize-website-views="website.template_header_default"
|
||||
data-customize-website-variable="'...'"
|
||||
data-img="..."/>
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<template id="..." inherit_id="..." name="..." active="True"/>
|
||||
<template id="..." inherit_id="..." name="..." active="False"/>
|
||||
|
||||
.. example::
|
||||
**Changing the menu items' horizontal alignment**
|
||||
|
||||
.. code-block:: xml
|
||||
:caption: ``/website_airproof/data/presets.xml``
|
||||
|
||||
<record id="website.template_header_default_align_center" model="ir.ui.view">
|
||||
<field name="active" eval="True"/>
|
||||
</record>
|
||||
|
||||
The same logic can be used for others Odoo apps as well.
|
||||
|
||||
**eCommerce - Display products categories**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<record id="website_sale.products_categories" model="ir.ui.view">
|
||||
<field name="active" eval="False"/>
|
||||
</record>
|
||||
|
||||
**Portal - Disable the language selector**
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<record id="portal.footer_language_selector" model="ir.ui.view">
|
||||
<field name="active" eval="False"/>
|
||||
</record>
|
||||
|
||||
Assets
|
||||
======
|
||||
|
||||
For this part, we will refer to the `assets_frontend` bundle located in the web module. This bundle
|
||||
specifies the list of assets loaded by the Website Builder, and the goal is to add your SCSS and JS
|
||||
files to the bundle.
|
||||
|
||||
Styles
|
||||
------
|
||||
|
||||
The Website Builder together with Bootstrap are great for defining the basic styles of your website.
|
||||
But to design something unique, you should go a step further. For this, you can easily add any SCSS
|
||||
file to your theme.
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``/website_airproof/__manifest__.py``
|
||||
|
||||
'assets': {
|
||||
'web.assets_frontend': [
|
||||
'website_airproof/static/src/scss/theme.scss',
|
||||
],
|
||||
},
|
||||
|
||||
Feel free to reuse the variables from your Bootstrap file and the ones used by Odoo in your
|
||||
:file:`theme.scss` file.
|
||||
|
||||
.. example::
|
||||
.. code-block:: javascript
|
||||
:caption: ``/website_airproof/static/src/scss/theme.scss``
|
||||
|
||||
blockquote {
|
||||
border-radius: $rounded-pill;
|
||||
color: o-color('o-color-3');
|
||||
font-family: o-website-value('headings-font');
|
||||
}
|
||||
|
||||
Interactivity
|
||||
-------------
|
||||
|
||||
Odoo supports three different kinds of JavaScript files:
|
||||
|
||||
- :ref:`plain JavaScript files <frontend/modules/plain_js>` (no module system),
|
||||
- :ref:`native JavaScript module <frontend/modules/native_js>`, and
|
||||
- :ref:`Odoo modules <frontend/modules/odoo_module>` (using a custom module system).
|
||||
|
||||
Most new Odoo JavaScript codes should use the native JavaScript module system. It's simpler and
|
||||
brings the benefit of a better developer experience with better integration with the IDE.
|
||||
|
||||
.. important::
|
||||
Odoo needs to know which files should be translated into :ref:`Odoo modules
|
||||
<frontend/js_modules>` and which files should not. It's an opt-in system: Odoo looks at the first
|
||||
line of a JavaScript file and checks if it contains the string `@odoo-module`. If so,
|
||||
it will automatically be converted to an Odoo module.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
|
||||
**Declaration**
|
||||
|
||||
.. code-block:: python
|
||||
:caption: ``/website_airproof/__manifest__.py``
|
||||
|
||||
'assets': {
|
||||
'web.assets_frontend': [
|
||||
'website_airproof/static/src/js/theme.js',
|
||||
],
|
||||
},
|
||||
|
||||
.. note::
|
||||
If you want to include files from an external library, you can add them to the :file:`/lib`
|
||||
folder of your module.
|
||||
|
||||
.. tip::
|
||||
- Use a linter (JSHint, ...).
|
||||
- Never add minified JavaScript libraries.
|
||||
- Add `'use strict';` on top of every Odoo JavaScript module.
|
||||
- Variables and functions should be *camelcased* (`myVariable`) instead of *snakecased*
|
||||
(`my_variable`).
|
||||
- Do not name a variable `event`; use `ev.` instead. This is to avoid bugs on non-Chrome
|
||||
browsers, as Chrome is magically assigning a global event variable (so if you use the event
|
||||
variable without declaring it, it will work fine on Chrome but crash on every other browser).
|
||||
- Use strict comparisons (`===` instead of `==`).
|
||||
- Use double quotes for all textual strings (such as `"Hello"`) and single quotes for all other
|
||||
strings, such as a CSS selector `.x_nav_item`.
|
||||
- Always use `this._super.apply(this, arguments)`.
|
||||
|
||||
.. seealso::
|
||||
- `Odoo JavaScript coding guidelines <https://github.com/odoo/odoo/wiki/Javascript-coding-guidelines>`_
|
||||
- :doc:`Overview of the Odoo JavaScript framework
|
||||
<../../reference/frontend/javascript_reference>`
|
||||
- `Odoo Experience Talk: 10 Tips to take your website design to the next level! <https://www.youtube.com/watch?v=vAgE_fPVXUQ&ab_channel=Odoo>`_
|
BIN
content/developer/howtos/website_themes/theming/dashboard.png
Normal file
After Width: | Height: | Size: 339 KiB |
BIN
content/developer/howtos/website_themes/theming/purple.png
Normal file
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 324 KiB |
After Width: | Height: | Size: 15 KiB |
BIN
content/developer/howtos/website_themes/theming/theme-colors.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
69
content/developer/howtos/website_themes/translations.rst
Normal file
@ -0,0 +1,69 @@
|
||||
============
|
||||
Translations
|
||||
============
|
||||
|
||||
With Odoo, you can translate your website into different languages.
|
||||
|
||||
In this chapter, you will learn how to:
|
||||
|
||||
- Translate the content of a module.
|
||||
- Import and export translations.
|
||||
- Integrate translations to a module.
|
||||
|
||||
Frontend
|
||||
========
|
||||
|
||||
To translate your pages with the Website Builder, go to your website and click on the language
|
||||
selector to switch to it. If your website was never translated to the target language, click
|
||||
:guilabel:`Add a language...`, select it in the pop-up window, and click :guilabel:`Add`.
|
||||
|
||||
Click :guilabel:`Translate` to start translating. Depending on the language, some text is
|
||||
automatically translated and highlighted in green, while everything that should be translated
|
||||
manually is highlighted in yellow.
|
||||
|
||||
.. image:: translations/translate-button.png
|
||||
:alt: Translate button
|
||||
:width: 570
|
||||
|
||||
Backend
|
||||
=======
|
||||
|
||||
Translating pages directly from the backend allows you to translate several languages at the same
|
||||
time. To do so, go to :menuselection:`Settings --> Technical --> User Interface: Views`, search for
|
||||
the name of the page you want to translate, and click the :guilabel:`Edit Translations` button.
|
||||
|
||||
.. image:: translations/edit-translations.png
|
||||
:alt: Edit translations
|
||||
:width: 718
|
||||
|
||||
Export
|
||||
======
|
||||
|
||||
Once you are done translating, you need to export the translations to integrate them into your
|
||||
module. To export everything at once, open your database, activate :ref:`developer mode
|
||||
<developer-mode>`, and go to :menuselection:`Settings --> Translations --> Export Translation`.
|
||||
Select the :guilabel:`Language` you translated, *PO File* under :guilabel:`File Format`, and
|
||||
*website_airproof* as the :guilabel:`Apps To Export`.
|
||||
|
||||
Download the file and move it to the :file:`i18n` folder. If needed, you can manually edit the
|
||||
:file:`.po` file afterward.
|
||||
|
||||
PO file
|
||||
=======
|
||||
|
||||
You can translate directly by editing a :file:`.po` file or creating the file yourself. Check out
|
||||
the :doc:`translating modules documentation <../translations>` to write your translations.
|
||||
|
||||
.. code-block:: po
|
||||
:caption: ``/website_coconuts/i18n/fr_BE.po``
|
||||
|
||||
#. module: website_airproof
|
||||
#: model_terms:ir.ui.view,arch_db:website_airproof.s_custom_snippet
|
||||
msgid "..."
|
||||
msgstr "..."
|
||||
|
||||
Import
|
||||
======
|
||||
|
||||
To import your translation files into Odoo, go to :menuselection:`Settings --> Translations -->
|
||||
Import Translation` and upload them.
|
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 6.1 KiB |
BIN
content/developer/howtos/website_themes/web-design.png
Normal file
After Width: | Height: | Size: 86 KiB |
@ -48,6 +48,7 @@ applications/services/fsm/default_warehouse.rst applications/services/field_serv
|
||||
|
||||
developer/howtos/rdtraining/D_mixins.rst developer/tutorials/mixins.rst # reorganize the developer doc
|
||||
developer/howtos/rdtraining/N_security.rst developer/tutorials/security.rst # reorganize the developer doc
|
||||
developer/howtos/themes.rst developer/howtos/website_themes.rst
|
||||
|
||||
# developer/misc
|
||||
|
||||
|