[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>
@ -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
|
||||||
|
@ -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`
|
|
||||||
|
@ -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
|
||||||
|
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
@ -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%
|
||||||
|
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 334 KiB |
Before Width: | Height: | Size: 13 KiB |
42
content/developer/tutorials/master_odoo_web_framework.rst
Normal 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`
|
@ -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::
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 453 KiB After Width: | Height: | Size: 453 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@ -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
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 2.0 MiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
@ -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%
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
@ -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::
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 382 KiB After Width: | Height: | Size: 382 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 813 KiB After Width: | Height: | Size: 813 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 698 KiB After Width: | Height: | Size: 698 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
@ -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::
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
@ -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
|
||||||
|