[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>
This commit is contained in:
CVDE-odoo 2023-04-20 14:32:38 +00:00 committed by Jonathan Castillo (jcs)
parent e650e86173
commit 892fd3e2ac
53 changed files with 3154 additions and 1110 deletions

View File

@ -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
------------

View File

@ -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

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

View 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

View 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>`_

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View 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

View 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;

View 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>`

View 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>

View 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>

View 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>

View 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">&nbsp;</div>
<div class="media_iframe_video_size" contenteditable="false">&nbsp;</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

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View 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`

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View 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.

View 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>`_

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View 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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@ -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