[IMP] developer/tutorials: separate js framework tutorial in two parts

This commit splits the 7 chapters of the JS tutorial in two
smaller and more focused tutorials:
- a basic one (Discover the JS framework)
- and an advanced one (Master the odoo web framework)

closes odoo/documentation#4243

Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
Géry Debongnie 2023-04-24 10:37:04 +00:00 committed by Antoine Vandevenne (anv)
parent 1da701d69f
commit b6b9de70d2
62 changed files with 319 additions and 309 deletions

View File

@ -10,6 +10,7 @@ Tutorials
tutorials/getting_started tutorials/getting_started
tutorials/discover_js_framework tutorials/discover_js_framework
tutorials/master_odoo_web_framework
tutorials/define_module_data tutorials/define_module_data
tutorials/restrict_data_access tutorials/restrict_data_access
tutorials/unit_tests tutorials/unit_tests
@ -31,9 +32,16 @@ Tutorials
:tag: Beginner :tag: Beginner
:large: :large:
Learn everything you need to know about the JavaScript framework of Odoo. This tutorial will Learn the basics of the JavaScript framework of Odoo. This tutorial will teach you how to work
teach you how to build custom components and views, give life to your application, and even with Owl components and introduce the basic principles underlying the Odoo JavaScript
re-introduce the kitten mode. codebase.
.. card:: Master the Odoo Web Framework
:target: tutorials/master_odoo_web_framework
:tag: Advanced
Become an expert in the Odoo Web Framework. A large variety of features are covered such as
fields, views, and even the kitten mode.
.. card:: Define module data .. card:: Define module data
:target: tutorials/define_module_data :target: tutorials/define_module_data

View File

@ -1,8 +1,8 @@
:show-content: :show-content:
================================= =========================
Discover the JavaScript Framework Discover the JS Framework
================================= =========================
.. toctree:: .. toctree::
:titlesonly: :titlesonly:
@ -10,50 +10,36 @@ Discover the JavaScript Framework
discover_js_framework/* discover_js_framework/*
For this training, we will step into the shoes of the IT staff at the fictional company Awesome This tutorial is designed to introduce you to the basics of the Odoo Javascript framework. Whether
T-Shirt, which is dedicated to printing custom t-shirts for online customers. The Awesome T-Shirt you are new to the framework or have some prior experience, this tutorial will provide you with a
company uses Odoo to manage orders and has created a dedicated Odoo module to manage their workflow. solid foundation for using the Odoo JavaScript framework in your projects.
The project is currently a simple kanban view, with a few columns.
The usual process is as follows: a customer looking for a nice t-shirt can simply order it from the This tutorial is divided into two parts. The first part covers the basics of Owl components, which
Awesome T-Shirt site and give the url for any image they want. They must also fill in some basic are a key part of the Odoo JS framework. Owl components are reusable UI components that can be used
information, such as the desired size and quantity of t-shirts. Once they have confirmed their to build complex web interfaces quickly and efficiently. We will explore how to create and use Owl
order, and once the payment has been validated, the system will create a task in our application. components in Odoo.
The big boss of Awesome T-shirt, Bafien Carpink, is unhappy with our implementation. He believes The second part of the tutorial focuses on creating a dashboard using various features of Odoo.
that by micromanaging more, he will be able to get more revenue from his employees. As the IT staff Dashboards are an essential part of any web application, and provide a nice starting point to use
for Awesome T-shirt, we are responsible with improving the system. Various independent tasks must be and interact with the Odoo codebase.
performed.
Let us now practice our Odoo skills! This tutorial assumes that you have some basic knowledge of development with Odoo in general
(models, controllers, QWeb, ...). If you are new to Odoo, we recommend that you start with the
:doc:`Getting started </developer/tutorials/getting_started>` tutorial before proceeding with this
one.
.. _howtos/discover_js_framework/setup: .. _tutorials/discover_js_framework/setup:
Setup Setup
===== =====
To follow the training, it is necessary to have basic knowledge on Git and a recent version of Odoo #. Clone the `official Odoo tutorials repository <https://github.com/odoo/tutorials>`_ and switch to
installed. If you have not installed it yet, we recommend installing it from :ref:`source
<setup/install/source>` (:dfn:`running Odoo from source code`).
To setup your development environment, you can also follow the dedicated chapter in :doc:`Getting
Started: Development environment setup <../tutorials/getting_started/02_setup>` tutorial.
The last things to do are:
- Clone the `official Odoo tutorials repository <https://github.com/odoo/tutorials>`_ and switch to
the branch `{BRANCH}`. the branch `{BRANCH}`.
- Add the cloned repository to the :option:`--addons-path <odoo-bin --addons-path>`. #. Add the cloned repository to the :option:`--addons-path <odoo-bin --addons-path>`.
- Start a new Odoo database and install the modules `owl_playground`, `awesome_tshirt`, and #. Start a new Odoo database and install the modules `owl_playground` and `awesome_tshirt`.
`awesome_gallery`.
Exercises Content
========= =======
* :doc:`discover_js_framework/01_components` - :doc:`discover_js_framework/01_owl_components`
* :doc:`discover_js_framework/02_odoo_web_framework` - :doc:`discover_js_framework/02_web_framework`
* :doc:`discover_js_framework/03_fields_and_views`
* :doc:`discover_js_framework/04_miscellaneous`
* :doc:`discover_js_framework/05_custom_kanban_view`
* :doc:`discover_js_framework/06_creating_view_from_scratch`
* :doc:`discover_js_framework/07_testing`

View File

@ -1,6 +1,6 @@
===================== =========================
Chapter 1: Components Chapter 1: Owl Components
===================== =========================
This chapter introduces the `Owl framework <https://github.com/odoo/owl>`_, a tailor-made component This chapter introduces the `Owl framework <https://github.com/odoo/owl>`_, a tailor-made component
system for Odoo. The main building blocks of OWL are `components system for Odoo. The main building blocks of OWL are `components
@ -10,28 +10,51 @@ In Owl, every part of user interface is managed by a component: they hold the lo
templates that are used to render the user interface. In practice, a component is represented by a templates that are used to render the user interface. In practice, a component is represented by a
small JavaScript class subclassing the `Component` class. small JavaScript class subclassing the `Component` class.
.. _jstraining/chapter1/intro_example: Before getting into the exercises, make sure you have followed all the steps described in this
:ref:`tutorial introduction <tutorials/discover_js_framework/setup>`.
.. example:: .. spoiler:: Solutions
The `Counter` class implements a component that holds the internal state of a counter and defines
how it should be incremented. The solutions for each exercise of the chapter are hosted on the `official Odoo tutorials
repository <https://github.com/odoo/tutorials/commits/{BRANCH}-solutions/owl_playground>`_. It is
recommended to try to solve them first without looking at the solution!
.. tip::
If you use Chrome as your web browser, you can install the `Owl Devtools` extension. This
extension provides many features to help you understand and profile any Owl application.
`Video: How to use the DevTools <https://www.youtube.com/watch?v=IUyQjwnrpzM>`_
In this chapter, we use the `owl_playground` addon, which provides a simplified environment that
only contains Owl and a few other files. The goal is to learn Owl itself, without relying on Odoo
web client code. To get started, open the `/owl_playground/playground` route with your browser: it
should display an Owl component with the text *hello world*.
Example: a `Counter` component
==============================
First, let us have a look at a simple example. The `Counter` component shown below is a component
that maintains an internal number value, displays it, and updates it whenever the user clicks on the
button.
.. code-block:: js .. code-block:: js
const { Component, useState } = owl; import { Component, useState } from "@odoo/owl";
class Counter extends Component { class Counter extends Component {
static template = "my_module.Counter"; static template = "my_module.Counter";
setup() {
state = useState({ value: 0 }); state = useState({ value: 0 });
}
increment() { increment() {
this.state.value++; this.state.value++;
} }
} }
The `Counter` class specifies the name of the template to render. The template is written in XML The `Counter` component specifies the name of the template to render. The template is written in XML
and defines a part of user interface. and defines a part of user interface:
.. code-block:: xml .. code-block:: xml
@ -43,25 +66,8 @@ small JavaScript class subclassing the `Component` class.
</templates> </templates>
You maybe noticed the `owl="1"` temporary attribute, it allows Odoo to differentiate Owl You maybe noticed the `owl="1"` temporary attribute, it allows Odoo to differentiate Owl
templates from the old JavaScript framework templates. templates from the old JavaScript framework templates. Note that Owl templates are not the same
as QWeb templates: they can contain additional directives, such as `t-on-click`.
Let us take some time to get used to Owl itself. Below, you will find a series of exercises
intended to quickly understand and practice the basics of Owl.
.. todo:: update screenshot
.. admonition:: Goal
Here is an overview of what we are going to achieve in this chapter.
.. image:: 01_components/overview.png
:scale: 50%
:align: center
.. spoiler:: Solutions
The solutions for each exercise of the chapter are hosted on the `official Odoo tutorials
repository <https://github.com/odoo/tutorials/commits/{BRANCH}-solutions/owl_playground>`_.
1. Displaying a counter 1. Displaying a counter
======================= =======================
@ -70,14 +76,10 @@ As a first exercise, let us implement a counter in the `Playground` component lo
:file:`owl_playground/static/src/`. To see the result, you can go to the `/owl_playground/playground` :file:`owl_playground/static/src/`. To see the result, you can go to the `/owl_playground/playground`
route with your browser. route with your browser.
.. tip::
The Odoo JavaScript files downloaded by the browser are minified. For debugging purpose, it's
easier when the files are not minified. Switch to :ref:`debug mode with assets <developer-mode/url>` so that the files are not minified.
.. exercise:: .. exercise::
#. Modify :file:`playground.js` so that it acts as a counter like in :ref:`the example above #. Modify :file:`playground.js` so that it acts as a counter like in the example above. You will
<jstraining/chapter1/intro_example>`. You will need to use the `useState need to use the `useState
<{OWL_PATH}/doc/reference/hooks.md#usestate>`_ function so that the component is re-rendered <{OWL_PATH}/doc/reference/hooks.md#usestate>`_ function so that the component is re-rendered
whenever any part of the state object has been read by this component is modified. whenever any part of the state object has been read by this component is modified.
#. In the same component, create an `increment` method. #. In the same component, create an `increment` method.
@ -87,12 +89,14 @@ route with your browser.
<{OWL_PATH}/doc/reference/event_handling.md#event-handling>`_ attribute in the button to <{OWL_PATH}/doc/reference/event_handling.md#event-handling>`_ attribute in the button to
trigger the `increment` method whenever the button is clicked. trigger the `increment` method whenever the button is clicked.
.. image:: 01_components/counter.png .. image:: 01_owl_components/counter.png
:scale: 70% :scale: 70%
:align: center :align: center
.. seealso:: .. tip::
`Video: How to use the DevTools <https://www.youtube.com/watch?v=IUyQjwnrpzM>`_ The Odoo JavaScript files downloaded by the browser are minified. For debugging purpose, it's
easier when the files are not minified. Switch to
:ref:`debug mode with assets <developer-mode/url>` so that the files are not minified.
2. Extract counter in a component 2. Extract counter in a component
================================= =================================
@ -138,7 +142,7 @@ todos. This will be done incrementally in multiple exercises that will introduce
this.todo = { id: 3, description: "buy milk", done: false }; this.todo = { id: 3, description: "buy milk", done: false };
} }
.. image:: 01_components/todo.png .. image:: 01_owl_components/todo.png
:scale: 70% :scale: 70%
:align: center :align: center
@ -178,7 +182,7 @@ list.
<{OWL_PATH}/doc/reference/templates.md#loops>`_ in the template. <{OWL_PATH}/doc/reference/templates.md#loops>`_ in the template.
#. Think about how it should be keyed with the `t-key` directive. #. Think about how it should be keyed with the `t-key` directive.
.. image:: 01_components/todo_list.png .. image:: 01_owl_components/todo_list.png
:scale: 70% :scale: 70%
:align: center :align: center
@ -207,7 +211,7 @@ a todo to the list.
this.todos = useState([]); this.todos = useState([]);
.. image:: 01_components/create_todo.png .. image:: 01_owl_components/create_todo.png
:scale: 70% :scale: 70%
:align: center :align: center
@ -248,7 +252,7 @@ way to do this is by using a `callback prop
`toggleState` function with the todo id. `toggleState` function with the todo id.
#. Make it work! #. Make it work!
.. image:: 01_components/toggle_todo.png .. image:: 01_owl_components/toggle_todo.png
:scale: 70% :scale: 70%
:align: center :align: center
@ -260,9 +264,10 @@ The final touch is to let the user delete a todo.
.. exercise:: .. exercise::
#. Add a new callback prop `removeTodo`. #. Add a new callback prop `removeTodo`.
#. Insert :code:`<span class="fa fa-remove">` in the template of the `Todo` component.
#. Whenever the user clicks on it, it should call the `removeTodo` method.
.. tip:: .. tip::
If you're using an array to store your todo list, you can use the JavaScript `splice` function If you're using an array to store your todo list, you can use the JavaScript `splice` function
to remove a todo from it. to remove a todo from it.
@ -275,10 +280,7 @@ The final touch is to let the user delete a todo.
list.splice(index, 1); list.splice(index, 1);
} }
#. Insert :code:`<span class="fa fa-remove">` in the template of the `Todo` component. .. image:: 01_owl_components/delete_todo.png
#. Whenever the user clicks on it, it should call the `removeTodo` method.
.. image:: 01_components/delete_todo.png
:scale: 70% :scale: 70%
:align: center :align: center
@ -322,7 +324,7 @@ components. This is useful to factorize the common layout between different part
#. Bonus point: if the `title` slot is not given, the `h5` should not be rendered at all. #. Bonus point: if the `title` slot is not given, the `h5` should not be rendered at all.
.. image:: 01_components/card.png .. image:: 01_owl_components/card.png
:scale: 70% :scale: 70%
:align: center :align: center

View File

@ -1,9 +1,9 @@
============================= =============================
Chapter 2: Odoo web framework Chapter 2: Odoo Web Framework
============================= =============================
In the previous chapter, we learned to use Owl framework and its different concepts. We can now The first part of this tutorial introduced you to most of Owl ideas. It is now time to learn
learn how to use the Odoo JavaScript framework which is is built on top of Owl. about the Odoo JavaScript framework in its entirety, as used by the web client.
.. graph TD .. graph TD
.. subgraph "Owl" .. subgraph "Owl"
@ -16,19 +16,16 @@ learn how to use the Odoo JavaScript framework which is is built on top of Owl.
.. odoo[Odoo JavaScript framework] --> Owl .. odoo[Odoo JavaScript framework] --> Owl
.. figure:: 02_odoo_web_framework/previously_learned.svg .. figure:: 02_web_framework/previously_learned.svg
:align: center :align: center
:width: 50% :width: 50%
This is the progress that we have made in discovering the JavaScript web framework at the end of For this chapter, we will start from the empty dashboard provided by the `awesome_tshirt`
:doc:`01_components`. addon. We will progressively add features to it, using the odoo framework.
In the `awesome_tshirt` module, we will build our Awesome dashboard. This will be a good
opportunity to discover many useful features in the Odoo JavaScript framework.
.. admonition:: Goal .. admonition:: Goal
.. image:: 02_odoo_web_framework/overview_02.png .. image:: 02_web_framework/overview_02.png
:align: center :align: center
.. spoiler:: Solutions .. spoiler:: Solutions
@ -49,7 +46,7 @@ and a main content zone just below. This is done using a `Layout component
`Layout` component. You can use :code:`{ "top-right": false, "bottom-right": false }` for the `Layout` component. You can use :code:`{ "top-right": false, "bottom-right": false }` for the
`display` props of the `Layout` component. `display` props of the `Layout` component.
.. image:: 02_odoo_web_framework/new_layout.png .. image:: 02_web_framework/new_layout.png
:align: center :align: center
.. seealso:: .. seealso::
@ -97,7 +94,7 @@ services, and components can import a service with the `useService()` hooks.
#. A button `Cancelled Order`, which opens a list of all orders created in the last 7 days, but #. A button `Cancelled Order`, which opens a list of all orders created in the last 7 days, but
already cancelled. already cancelled.
.. image:: 02_odoo_web_framework/navigation_buttons.png .. image:: 02_web_framework/navigation_buttons.png
:align: center :align: center
.. seealso:: .. seealso::
@ -150,7 +147,7 @@ Here is a short explanation on the various arguments:
- Number of cancelled orders this month - Number of cancelled orders this month
- Average time for an order to go from 'new' to 'sent' or 'cancelled' - Average time for an order to go from 'new' to 'sent' or 'cancelled'
.. image:: 02_odoo_web_framework/statistics.png .. image:: 02_web_framework/statistics.png
:align: center :align: center
.. seealso:: .. seealso::
@ -222,7 +219,7 @@ chartjs code every time if they don't need it).
correct quantity for each sold t-shirts in each size (that information is available in the correct quantity for each sold t-shirts in each size (that information is available in the
statistics route). statistics route).
.. image:: 02_odoo_web_framework/pie_chart.png .. image:: 02_web_framework/pie_chart.png
:align: center :align: center
:scale: 50% :scale: 50%
@ -245,7 +242,7 @@ Here is a list of some small improvements you could try to do if you have the ti
corresponding size. corresponding size.
#. Add a SCSS file and see if you can change the background color of the dashboard action. #. Add a SCSS file and see if you can change the background color of the dashboard action.
.. image:: 02_odoo_web_framework/misc.png .. image:: 02_web_framework/misc.png
:align: center :align: center
:scale: 50% :scale: 50%

Binary file not shown.

Before

Width:  |  Height:  |  Size: 334 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,42 @@
:show-content:
=============================
Master the Odoo Web Framework
=============================
.. toctree::
:titlesonly:
:glob:
master_odoo_web_framework/*
This tutorial is designed for those who have completed the :doc:`discover_js_framework` tutorial and
are looking to deepen their knowledge of the Odoo web framework.
For this training, we will step into the shoes of the IT staff at the fictional company Awesome
T-Shirt, which is dedicated to printing custom t-shirts for online customers. The Awesome T-Shirt
company uses Odoo to manage orders and has created a dedicated Odoo module to manage their workflow.
In this tutorial, we will explore various aspects of the Odoo web framework in detail, including
fields and views, notifications, command palette, and much more. This tutorial will provide you with
the knowledge and skills you need to take full advantage of the Odoo web framework. So, let's get
started!
.. _howtos/master_odoo_web_framework/setup:
Setup
=====
#. Clone the `official Odoo tutorials repository <https://github.com/odoo/tutorials>`_ and switch to
the branch `{BRANCH}`.
#. Add the cloned repository to the :option:`--addons-path <odoo-bin --addons-path>`.
#. Start a new Odoo database and install the modules `awesome_tshirt` and `awesome_gallery`.
Content
=======
- :doc:`master_odoo_web_framework/01_fields_and_views`
- :doc:`master_odoo_web_framework/02_miscellaneous`
- :doc:`master_odoo_web_framework/03_custom_kanban_view`
- :doc:`master_odoo_web_framework/04_creating_view_from_scratch`
- :doc:`master_odoo_web_framework/05_testing`

View File

@ -1,56 +1,32 @@
=========================== ===========================
Chapter 3: Fields and Views Chapter 1: Fields and Views
=========================== ===========================
In the previous chapter, we learned a range of skills, including how to create and use services, In the previous chapter, we learned a range of skills, including how to create and use services,
work with the Layout component, make the dashboard translatable, and lazy load a JavaScript library work with the Layout component, make the dashboard translatable, and lazy load a JavaScript library
like Chart.js. Now, let's move on to learning how to create new fields and views. like Chart.js. Now, let's learn how to create new fields and views.
.. graph TD .. spoiler:: Solutions
.. subgraph "Owl"
.. C[Component]
.. T[Template]
.. H[Hook]
.. S[Slot]
.. E[Event]
.. end
.. subgraph "odoo"[Odoo Javascript framework] The solutions for each exercise of the chapter are hosted on the `official Odoo tutorials
.. Services repository <https://github.com/odoo/tutorials/commits/{BRANCH}-solutions/awesome_tshirt>`_. It is
.. Translation recommended not to look at them before trying the exercises.
.. lazy[Lazy loading libraries]
.. SCSS
.. action --> Services
.. rpc --> Services
.. end
.. odoo[Odoo JavaScript framework] --> Owl
.. figure:: 03_fields_and_views/previously_learned.svg
:align: center
:width: 60%
This is the progress that we have made in discovering the JavaScript web framework at the end of
:doc:`02_odoo_web_framework`.
Fields and views are among the most important concepts in the Odoo user interface. They are key to Fields and views are among the most important concepts in the Odoo user interface. They are key to
many important user interactions, and should therefore work perfectly. many important user interactions, and should therefore work perfectly. In the context of the
JavaScript framework, fields are components specialized for visualizing/editing a specific field for
In the context of the JavaScript framework, fields are components specialized for a given record. For example, a (Python) model may define a char field, which will be represented by
visualizing/editing a specific field for a given record. a field component `CharField`.
For example, a (Python) model may define a char field, which will be represented by a field
component `CharField`.
A field component is basically just a component registered in the `fields` :ref:`registry A field component is basically just a component registered in the `fields` :ref:`registry
<frontend/registries>`. The field component may define some additional static keys (metadata), such <frontend/registries>`. The field component may define some additional static keys (metadata), such
as `displayName` or `supportedTypes`, and the most important one: `extractProps`, which prepare the as `displayName` or `supportedTypes`, and the most important one: `extractProps`, which prepare the
base props received by the `CharField`. base props received by the `CharField`.
.. example:: Example: a simple field
Let us discuss a simplified implementation of a `CharField`. =======================
First, here is the template: Let us discuss a simplified implementation of a `CharField`. First, here is the template:
.. code-block:: xml .. code-block:: xml
@ -105,10 +81,10 @@ base props received by the `CharField`.
There are a few important things to notice: There are a few important things to notice:
- The `CharField` receives its (raw) value in props. It needs to format it before displaying it. - The `CharField` receives its (raw) value in props. It needs to format it before displaying it.
- It receives an `update` function in its props, which is used by the field to notify the owner - It receives an `update` function in its props, which is used by the field to notify the owner of
of the state that the value of this field has been changed. Note that the field does not (and the state that the value of this field has been changed. Note that the field does not (and should
should not) maintain a local state with its value. Whenever the change has been applied, it not) maintain a local state with its value. Whenever the change has been applied, it will come
will come back (possibly after an onchange) by the way of the props. back (possibly after an onchange) by the way of the props.
- It defines an `extractProps` function. This is a step that translates generic standard props, - It defines an `extractProps` function. This is a step that translates generic standard props,
specific to a view, to specialized props, useful to the component. This allows the component to specific to a view, to specialized props, useful to the component. This allows the component to
have a better API, and may make it so that it is reusable. have a better API, and may make it so that it is reusable.
@ -122,16 +98,6 @@ views (namely: `form`, `list`, `kanban`) by using the `widget` attribute.
<field name="preview_moves" widget="account_resequence_widget"/> <field name="preview_moves" widget="account_resequence_widget"/>
.. admonition:: Goal
.. image:: 03_fields_and_views/overview_03.png
:align: center
.. spoiler:: Solutions
The solutions for each exercise of the chapter are hosted on the `official Odoo tutorials
repository <https://github.com/odoo/tutorials/commits/{BRANCH}-solutions/awesome_tshirt>`_.
1. An `image_preview` field 1. An `image_preview` field
=========================== ===========================
@ -155,10 +121,10 @@ field, so it can be edited.
#. Update the arch of the form view to use your new field by setting the `widget` attribute. #. Update the arch of the form view to use your new field by setting the `widget` attribute.
.. note:: .. note::
It is possible to solve this exercise by inheriting `CharField` , but the goal of this It is possible to solve this exercise by inheriting `CharField` , but the goal of this exercise
exercise is to create a field from scratch. is to create a field from scratch.
.. image:: 03_fields_and_views/image_field.png .. image:: 01_fields_and_views/image_field.png
:align: center :align: center
:scale: 50% :scale: 50%
@ -175,7 +141,7 @@ field, so it can be edited.
some action should be done. In particular, we want to display a warning "MISSING TSHIRT DESIGN" some action should be done. In particular, we want to display a warning "MISSING TSHIRT DESIGN"
in red if there is no image URL specified on the order. in red if there is no image URL specified on the order.
.. image:: 03_fields_and_views/missing_image.png .. image:: 01_fields_and_views/missing_image.png
:align: center :align: center
3. Customizing a field component 3. Customizing a field component
@ -195,7 +161,7 @@ whenever it is set to true.
#. Use it in the list/kanban/form view. #. Use it in the list/kanban/form view.
#. Modify it to add a red `Late` next to it, as requested. #. Modify it to add a red `Late` next to it, as requested.
.. image:: 03_fields_and_views/late_field.png .. image:: 01_fields_and_views/late_field.png
:align: center :align: center
.. seealso:: .. seealso::
@ -222,7 +188,7 @@ insert arbitrary components in the form view. Let us see how we can use it.
material". material".
- Make sure that your widget is updated in real time. - Make sure that your widget is updated in real time.
.. image:: 03_fields_and_views/warning_widget.png .. image:: 01_fields_and_views/warning_widget.png
:align: center :align: center
.. seealso:: .. seealso::
@ -250,7 +216,7 @@ the data has been marked explicitly with a `markup` function.
.. note:: .. note::
This is an example of a safe use of `t-out` , since the string is static. This is an example of a safe use of `t-out` , since the string is static.
.. image:: 03_fields_and_views/warning_widget2.png .. image:: 01_fields_and_views/warning_widget2.png
:align: center :align: center
6. Add buttons in the control panel 6. Add buttons in the control panel
@ -334,7 +300,7 @@ Most (or all?) Odoo views share a common architecture:
.. A --- C .. A --- C
.. ``` .. ```
.. image:: 03_fields_and_views/view_architecture.svg .. image:: 01_fields_and_views/view_architecture.svg
:align: center :align: center
:width: 75% :width: 75%
:class: o-no-modal :class: o-no-modal
@ -389,7 +355,7 @@ There is a service dedicated to calling models methods: `orm_service`, located i
task stage is `printed`. Otherwise, it is displayed as a secondary button. task stage is `printed`. Otherwise, it is displayed as a secondary button.
#. Bonus point: clicking twice on the button should not trigger 2 RPCs. #. Bonus point: clicking twice on the button should not trigger 2 RPCs.
.. image:: 03_fields_and_views/form_button.png .. image:: 01_fields_and_views/form_button.png
:align: center :align: center
.. seealso:: .. seealso::

View File

@ -1,5 +1,5 @@
======================== ========================
Chapter 4: Miscellaneous Chapter 2: Miscellaneous
======================== ========================
In the previous task, we learned how to create fields and views. There is still much more to In the previous task, we learned how to create fields and views. There is still much more to
@ -29,16 +29,16 @@ discover in the feature-rich Odoo web framework, so let's dive in and explore mo
.. odoo[Odoo JavaScript framework] --> Owl .. odoo[Odoo JavaScript framework] --> Owl
.. figure:: 04_miscellaneous/previously_learned.svg .. figure:: 02_miscellaneous/previously_learned.svg
:align: center :align: center
:width: 70% :width: 70%
This is the progress that we have made in discovering the JavaScript web framework at the end of This is the progress that we have made in discovering the JavaScript web framework at the end of
:doc:`03_fields_and_views`. :doc:`01_fields_and_views`.
.. admonition:: Goal .. admonition:: Goal
.. image:: 04_miscellaneous/kitten_mode.png .. image:: 02_miscellaneous/kitten_mode.png
:align: center :align: center
.. spoiler:: Solutions .. spoiler:: Solutions
@ -50,7 +50,7 @@ discover in the feature-rich Odoo web framework, so let's dive in and explore mo
=========================================== ===========================================
.. note:: .. note::
This task depends on :doc:`the previous exercises <03_fields_and_views>`. This task depends on :doc:`the previous exercises <01_fields_and_views>`.
After using the :guilabel:`Print Label` button for some t-shirt tasks, it is apparent that there After using the :guilabel:`Print Label` button for some t-shirt tasks, it is apparent that there
should be some feedback that the `print_label` action is completed (or failed, for example, the should be some feedback that the `print_label` action is completed (or failed, for example, the
@ -61,7 +61,7 @@ printer is not connected or ran out of paper).
completed successfully, and a warning if it failed. completed successfully, and a warning if it failed.
#. If it failed, the notification should be permanent. #. If it failed, the notification should be permanent.
.. image:: 04_miscellaneous/notification.png .. image:: 02_miscellaneous/notification.png
:align: center :align: center
:scale: 60% :scale: 60%
@ -87,7 +87,7 @@ notifications and provide access to certain features.
#. Bonus point: avoid making the initial RPC by adding the information to the session info. The #. Bonus point: avoid making the initial RPC by adding the information to the session info. The
session info is given to the web client by the server in the initial response. session info is given to the web client by the server in the initial response.
.. image:: 04_miscellaneous/systray.png .. image:: 02_miscellaneous/systray.png
:align: center :align: center
.. seealso:: .. seealso::
@ -139,7 +139,7 @@ by pressing `CTRL+K` in the Odoo interface.
Make sure that the command is only active whenever a field preview is visible in the screen. Make sure that the command is only active whenever a field preview is visible in the screen.
.. image:: 04_miscellaneous/new_command.png .. image:: 02_miscellaneous/new_command.png
:align: center :align: center
.. seealso:: .. seealso::
@ -197,11 +197,11 @@ these terms?".
#. Update the code to display the message on click by using the dialog service. You can use #. Update the code to display the message on click by using the dialog service. You can use
`ConfirmationDialog`. `ConfirmationDialog`.
.. image:: 04_miscellaneous/bafien_eye.png .. image:: 02_miscellaneous/bafien_eye.png
:align: center :align: center
:scale: 60% :scale: 60%
.. image:: 04_miscellaneous/confirmation_dialog.png .. image:: 02_miscellaneous/confirmation_dialog.png
:align: center :align: center
:scale: 60% :scale: 60%
@ -236,7 +236,7 @@ from a given customer.
#. Update the code to fetch the list of customers with the tshirt service, and display it in the #. Update the code to fetch the list of customers with the tshirt service, and display it in the
autocomplete component, filtered by the `fuzzyLookup` method. autocomplete component, filtered by the `fuzzyLookup` method.
.. image:: 04_miscellaneous/autocomplete.png .. image:: 02_miscellaneous/autocomplete.png
:align: center :align: center
:scale: 60% :scale: 60%
@ -274,7 +274,7 @@ the background of Odoo, because we like kittens.
#. Add a command to the command palette to toggle the kitten mode. Toggling the kitten mode #. Add a command to the command palette to toggle the kitten mode. Toggling the kitten mode
should toggle the `.o-kitten-mode` class and update the current URL accordingly. should toggle the `.o-kitten-mode` class and update the current URL accordingly.
.. image:: 04_miscellaneous/kitten_mode.png .. image:: 02_miscellaneous/kitten_mode.png
:align: center :align: center
8. Lazy loading our dashboard 8. Lazy loading our dashboard

View File

@ -1,11 +1,11 @@
============================= =============================
Chapter 5: Custom kanban view Chapter 3: Custom kanban view
============================= =============================
.. todo:: It'd be cool to follow the naming convention of the previous chapters: "Chapter N: The concept studied in the chapter" .. todo:: It'd be cool to follow the naming convention of the previous chapters: "Chapter N: The concept studied in the chapter"
.. warning:: .. warning::
It is highly recommended that you complete :doc:`03_fields_and_views` before starting this It is highly recommended that you complete :doc:`01_fields_and_views` before starting this
chapter. The concepts introduced in Chapter 3, including views and examples, will be essential chapter. The concepts introduced in Chapter 3, including views and examples, will be essential
for understanding the material covered in this chapter. for understanding the material covered in this chapter.
@ -21,7 +21,7 @@ orders linked to that customer.
.. admonition:: Goal .. admonition:: Goal
.. image:: 05_custom_kanban_view/overview.png .. image:: 03_custom_kanban_view/overview.png
:align: center :align: center
.. spoiler:: Solutions .. spoiler:: Solutions
@ -57,7 +57,7 @@ We will need to display a list of customers, so we might as well create the comp
#. Subclass the kanban controller to add `CustomerList` in its sub-components. #. Subclass the kanban controller to add `CustomerList` in its sub-components.
#. Make sure you see your component in the kanban view. #. Make sure you see your component in the kanban view.
.. image:: 05_custom_kanban_view/customer_list.png .. image:: 03_custom_kanban_view/customer_list.png
:align: center :align: center
:scale: 60% :scale: 60%
@ -70,7 +70,7 @@ We will need to display a list of customers, so we might as well create the comp
#. Display the list in the template with a `t-foreach`. #. Display the list in the template with a `t-foreach`.
#. Whenever a customer is selected, call the `selectCustomer` function prop. #. Whenever a customer is selected, call the `selectCustomer` function prop.
.. image:: 05_custom_kanban_view/customer_data.png .. image:: 03_custom_kanban_view/customer_data.png
:align: center :align: center
:scale: 60% :scale: 60%
@ -95,7 +95,7 @@ We will need to display a list of customers, so we might as well create the comp
}); });
} }
.. image:: 05_custom_kanban_view/customer_filter.png .. image:: 03_custom_kanban_view/customer_filter.png
:align: center :align: center
:scale: 60% :scale: 60%
@ -111,7 +111,7 @@ customers with an active order.
next to it. next to it.
#. Changing the value of the checkbox should filter the list on customers with an active order. #. Changing the value of the checkbox should filter the list on customers with an active order.
.. image:: 05_custom_kanban_view/active_customer.png .. image:: 03_custom_kanban_view/active_customer.png
:align: center :align: center
:scale: 60% :scale: 60%
@ -126,7 +126,7 @@ customers with an active order.
.. tip:: .. tip::
You can use the `fuzzyLookup` function to perform the filter. You can use the `fuzzyLookup` function to perform the filter.
.. image:: 05_custom_kanban_view/customer_search.png .. image:: 03_custom_kanban_view/customer_search.png
:align: center :align: center
:scale: 60% :scale: 60%
@ -164,6 +164,6 @@ us see how we could do it in a more declarative way, with the `t-model
This is actually pretty hard, in particular in combination with the filtering done in the This is actually pretty hard, in particular in combination with the filtering done in the
previous exercise. There are many edge cases to take into account. previous exercise. There are many edge cases to take into account.
.. image:: 05_custom_kanban_view/customer_pager.png .. image:: 03_custom_kanban_view/customer_pager.png
:align: center :align: center
:scale: 60% :scale: 60%

View File

@ -1,9 +1,9 @@
======================================= =======================================
Chapter 6: Creating a view from scratch Chapter 4: Creating a view from scratch
======================================= =======================================
.. warning:: .. warning::
It is highly recommended that you complete :doc:`03_fields_and_views` before starting this It is highly recommended that you complete :doc:`01_fields_and_views` before starting this
chapter. The concepts introduced in Chapter 3, including views and examples, will be essential chapter. The concepts introduced in Chapter 3, including views and examples, will be essential
for understanding the material covered in this chapter. for understanding the material covered in this chapter.
@ -30,7 +30,7 @@ addon includes the necessary server files to add a new view.
.. admonition:: Goal .. admonition:: Goal
.. image:: 06_creating_view_from_scratch/overview.png .. image:: 04_creating_view_from_scratch/overview.png
:align: center :align: center
.. spoiler:: Solutions .. spoiler:: Solutions
@ -53,10 +53,10 @@ First step is to create a JavaScript implementation with a simple component.
#. Add `gallery` as one of the view type in the orders action. #. Add `gallery` as one of the view type in the orders action.
#. Make sure that you can see your hello world component when switching to the gallery view. #. Make sure that you can see your hello world component when switching to the gallery view.
.. image:: 06_creating_view_from_scratch/view_button.png .. image:: 04_creating_view_from_scratch/view_button.png
:align: center :align: center
.. image:: 06_creating_view_from_scratch/new_view.png .. image:: 04_creating_view_from_scratch/new_view.png
:align: center :align: center
2. Use the Layout component 2. Use the Layout component
@ -71,7 +71,7 @@ have the standard features like other views.
#. Update the template to use `Layout`. It needs a `display` prop, which can be found in #. Update the template to use `Layout`. It needs a `display` prop, which can be found in
`props.display`. `props.display`.
.. image:: 06_creating_view_from_scratch/layout.png .. image:: 04_creating_view_from_scratch/layout.png
:align: center :align: center
3. Parse the arch 3. Parse the arch
@ -134,7 +134,7 @@ Let us now get some real data.
.. note:: .. note::
The loading data code will be moved into a proper model in the next exercise. The loading data code will be moved into a proper model in the next exercise.
.. image:: 06_creating_view_from_scratch/gallery_data.png .. image:: 04_creating_view_from_scratch/gallery_data.png
:align: center :align: center
5. Reorganize code 5. Reorganize code
@ -157,7 +157,7 @@ to learn how to structure code in Odoo. Also, this will scale better with changi
Update the renderer to display images in a nice way, if the field is set. If `image_field` is Update the renderer to display images in a nice way, if the field is set. If `image_field` is
empty, display an empty box instead. empty, display an empty box instead.
.. image:: 06_creating_view_from_scratch/tshirt_images.png .. image:: 04_creating_view_from_scratch/tshirt_images.png
:align: center :align: center
7. Switch to form view on click 7. Switch to form view on click
@ -189,7 +189,7 @@ It is useful to have some additional information on mouse hover.
char field, a number field or a many2one field. char field, a number field or a many2one field.
#. Update the orders gallery view to add the customer as tooltip field. #. Update the orders gallery view to add the customer as tooltip field.
.. image:: 06_creating_view_from_scratch/image_tooltip.png .. image:: 04_creating_view_from_scratch/image_tooltip.png
:align: center :align: center
:scale: 60% :scale: 60%
@ -204,7 +204,7 @@ It is useful to have some additional information on mouse hover.
Let's add a pager on the control panel and manage all the pagination like in a normal Odoo view. Let's add a pager on the control panel and manage all the pagination like in a normal Odoo view.
Note that it is surprisingly difficult. Note that it is surprisingly difficult.
.. image:: 06_creating_view_from_scratch/pagination.png .. image:: 04_creating_view_from_scratch/pagination.png
:align: center :align: center
.. seealso:: .. seealso::

View File

@ -1,5 +1,5 @@
================== ==================
Chapter 7: Testing Chapter 5: Testing
================== ==================
Automatically testing code is important when working on a codebase. It helps ensure we don't Automatically testing code is important when working on a codebase. It helps ensure we don't
@ -48,7 +48,7 @@ It is also useful to test independently a component or a piece of code. :ref:`QU
#. In the `awesome_tshirt` addon, add a :file:`static/tests/counter_tests.js` file. #. In the `awesome_tshirt` addon, add a :file:`static/tests/counter_tests.js` file.
#. Add a QUnit test that instantiates a counter, clicks on it, and makes sure it is incremented. #. Add a QUnit test that instantiates a counter, clicks on it, and makes sure it is incremented.
.. image:: 07_testing/component_test.png .. image:: 05_testing/component_test.png
:align: center :align: center
.. seealso:: .. seealso::
@ -63,7 +63,7 @@ Many components need more setup to be tested. In particular, we often need to mo
Let us see how to do that. Let us see how to do that.
.. note:: .. note::
This depends on our Gallery View from :doc:`06_creating_view_from_scratch`. This depends on our Gallery View from :doc:`04_creating_view_from_scratch`.
.. exercise:: .. exercise::
@ -72,7 +72,7 @@ Let us see how to do that.
#. Add another test that checks that when the user clicks on an image, it is switched to the form #. Add another test that checks that when the user clicks on an image, it is switched to the form
view of the corresponding order. view of the corresponding order.
.. image:: 07_testing/view_test.png .. image:: 05_testing/view_test.png
:align: center :align: center
.. seealso:: .. seealso::

View File

@ -61,3 +61,13 @@ developer/howtos/discover_js_framework/07_testing.rst developer/tutorials/discov
developer/reference/frontend/icons_library.rst contributing/development/ui/icons.rst # Odoo UI icons -> UI Icons developer/reference/frontend/icons_library.rst contributing/development/ui/icons.rst # Odoo UI icons -> UI Icons
developer/reference/frontend/javascript_cheatsheet.rst developer/howtos/javascript_create_field.rst # refactor JavaScript cheatsheet into howtos developer/reference/frontend/javascript_cheatsheet.rst developer/howtos/javascript_create_field.rst # refactor JavaScript cheatsheet into howtos
# developer/tutorials
developer/tutorials/discover_js_framework/01_components.rst developer/tutorials/discover_js_framework/01_owl_components.rst
developer/tutorials/discover_js_framework/02_odoo_web_framework.rst developer/tutorials/discover_js_framework/02_web_framework.rst
developer/tutorials/discover_js_framework/03_fields_and_views.rst developer/tutorials/master_odoo_web_framework/01_fields_and_views.rst
developer/tutorials/discover_js_framework/04_miscellaneous.rst developer/tutorials/master_odoo_web_framework/02_miscellaneous.rst
developer/tutorials/discover_js_framework/05_custom_kanban_view.rst developer/tutorials/master_odoo_web_framework/03_custom_kanban_view.rst
developer/tutorials/discover_js_framework/06_creating_view_from_scratch.rst developer/tutorials/master_odoo_web_framework/04_creating_view_from_scratch.rst
developer/tutorials/discover_js_framework/07_testing.rst developer/tutorials/master_odoo_web_framework/05_testing.rst