wip
@@ -396,7 +396,7 @@ some label and a pie chart.
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
And now, our dashboard template is now generic!
|
||||
And now, our dashboard template is generic!
|
||||
|
||||
10. Making our dashboard extensible
|
||||
===================================
|
||||
|
||||
@@ -11,7 +11,10 @@ Master the Odoo Web Framework
|
||||
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.
|
||||
are looking to deepen their knowledge of the Odoo web framework. It is organized in four independant
|
||||
chapters, each focusing on different features of Odoo.
|
||||
|
||||
Each of these chapters can be done independantly, in any order.
|
||||
|
||||
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
|
||||
@@ -35,8 +38,7 @@ Setup
|
||||
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`
|
||||
- :doc:`master_odoo_web_framework/01_build_clicker_game`
|
||||
- :doc:`master_odoo_web_framework/02_create_customize_fields`
|
||||
- :doc:`master_odoo_web_framework/03_create_gallery_view`
|
||||
- :doc:`master_odoo_web_framework/04_customize_kanban_view`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
========================
|
||||
Chapter 2: Miscellaneous
|
||||
========================
|
||||
===============================
|
||||
Chapter 1: Build a Clicker game
|
||||
===============================
|
||||
|
||||
In the previous task, we learned how to create fields and views. There is still much more to
|
||||
discover in the feature-rich Odoo web framework, so let's dive in and explore more in this chapter!
|
||||
@@ -29,7 +29,7 @@ discover in the feature-rich Odoo web framework, so let's dive in and explore mo
|
||||
|
||||
.. odoo[Odoo JavaScript framework] --> Owl
|
||||
|
||||
.. figure:: 02_miscellaneous/previously_learned.svg
|
||||
.. figure:: 01_build_clicker_game/previously_learned.svg
|
||||
:align: center
|
||||
:width: 70%
|
||||
|
||||
@@ -38,7 +38,7 @@ discover in the feature-rich Odoo web framework, so let's dive in and explore mo
|
||||
|
||||
.. admonition:: Goal
|
||||
|
||||
.. image:: 02_miscellaneous/kitten_mode.png
|
||||
.. image:: 01_build_clicker_game/kitten_mode.png
|
||||
:align: center
|
||||
|
||||
.. spoiler:: Solutions
|
||||
@@ -62,7 +62,7 @@ printer is not connected or ran out of paper).
|
||||
completed successfully, and a warning if it failed.
|
||||
#. If it failed, the notification should be permanent.
|
||||
|
||||
.. image:: 02_miscellaneous/notification.png
|
||||
.. image:: 01_build_clicker_game/notification.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
@@ -88,7 +88,7 @@ notifications and provide access to certain features.
|
||||
#. 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.
|
||||
|
||||
.. image:: 02_miscellaneous/systray.png
|
||||
.. image:: 01_build_clicker_game/systray.png
|
||||
:align: center
|
||||
|
||||
.. seealso::
|
||||
@@ -142,7 +142,7 @@ by pressing `CTRL+K` in the Odoo interface.
|
||||
|
||||
Ensure the command is only active whenever a field preview is visible on the screen.
|
||||
|
||||
.. image:: 02_miscellaneous/new_command.png
|
||||
.. image:: 01_build_clicker_game/new_command.png
|
||||
:align: center
|
||||
|
||||
.. seealso::
|
||||
@@ -194,11 +194,11 @@ be used in legal proceedings if necessary. Do you agree to these terms?"
|
||||
}
|
||||
}
|
||||
|
||||
.. image:: 02_miscellaneous/bafien_eye.png
|
||||
.. image:: 01_build_clicker_game/bafien_eye.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
.. image:: 02_miscellaneous/confirmation_dialog.png
|
||||
.. image:: 01_build_clicker_game/confirmation_dialog.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
@@ -228,7 +228,7 @@ from a given customer.
|
||||
component, filtered by the `fuzzyLookup
|
||||
<{GITHUB_PATH}/addons/web/static/src/core/utils/search.js>`_ method.
|
||||
|
||||
.. image:: 02_miscellaneous/autocomplete.png
|
||||
.. image:: 01_build_clicker_game/autocomplete.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
@@ -260,7 +260,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
|
||||
should toggle the class `o-kitten-mode` and update the current URL accordingly.
|
||||
|
||||
.. image:: 02_miscellaneous/kitten_mode.png
|
||||
.. image:: 01_build_clicker_game/kitten_mode.png
|
||||
:align: center
|
||||
|
||||
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,6 +1,6 @@
|
||||
===========================
|
||||
Chapter 1: Fields and Views
|
||||
===========================
|
||||
======================================
|
||||
Chapter 2: Create and Customize fields
|
||||
======================================
|
||||
|
||||
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
|
||||
@@ -122,7 +122,7 @@ to see the image itself in the form view.
|
||||
It is possible to solve this exercise by inheriting `CharField`, but the goal of this exercise is
|
||||
to create a field from scratch.
|
||||
|
||||
.. image:: 01_fields_and_views/image_field.png
|
||||
.. image:: 02_create_customize_fields/image_field.png
|
||||
:align: center
|
||||
:scale: 50%
|
||||
|
||||
@@ -140,7 +140,7 @@ action should be done.
|
||||
|
||||
Display a warning "MISSING TSHIRT DESIGN" in red if there is no image URL specified on the order.
|
||||
|
||||
.. image:: 01_fields_and_views/missing_image.png
|
||||
.. image:: 02_create_customize_fields/missing_image.png
|
||||
:align: center
|
||||
|
||||
3. Customizing a field component
|
||||
@@ -160,7 +160,7 @@ whenever it is set to `true`.
|
||||
#. Use it in the list/kanban/form view.
|
||||
#. Modify it to add a red `Late` next to it, as requested.
|
||||
|
||||
.. image:: 01_fields_and_views/late_field.png
|
||||
.. image:: 02_create_customize_fields/late_field.png
|
||||
:align: center
|
||||
|
||||
.. seealso::
|
||||
@@ -187,7 +187,7 @@ insert arbitrary components in the form view. Let us see how we can use it.
|
||||
.. tip::
|
||||
Try to evaluate `props.record` in the :guilabel:`Console` tab of your browser's dev tools.
|
||||
|
||||
.. image:: 01_fields_and_views/warning_widget.png
|
||||
.. image:: 02_create_customize_fields/warning_widget.png
|
||||
:align: center
|
||||
|
||||
.. seealso::
|
||||
@@ -216,7 +216,7 @@ is injected as HTML.
|
||||
.. note::
|
||||
This is an example of a safe use of `t-out`, since the string is static.
|
||||
|
||||
.. image:: 01_fields_and_views/warning_widget2.png
|
||||
.. image:: 02_create_customize_fields/warning_widget2.png
|
||||
:align: center
|
||||
|
||||
6. Add buttons in the control panel
|
||||
@@ -300,7 +300,7 @@ Most (or all?) Odoo views share a common architecture:
|
||||
.. A --- C
|
||||
.. ```
|
||||
|
||||
.. image:: 01_fields_and_views/view_architecture.svg
|
||||
.. image:: 02_create_customize_fields/view_architecture.svg
|
||||
:align: center
|
||||
:width: 75%
|
||||
:class: o-no-modal
|
||||
@@ -365,7 +365,7 @@ There is a service dedicated to calling models methods: `orm_service`, located i
|
||||
task stage is `printed`. Otherwise, it should be displayed as a secondary button.
|
||||
#. Bonus point: clicking twice on the button should not trigger 2 RPCs.
|
||||
|
||||
.. image:: 01_fields_and_views/form_button.png
|
||||
.. image:: 02_create_customize_fields/form_button.png
|
||||
:align: center
|
||||
|
||||
.. 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,6 +1,6 @@
|
||||
=======================================
|
||||
Chapter 4: Creating a view from scratch
|
||||
=======================================
|
||||
================================
|
||||
Chapter 3: Create a Gallery View
|
||||
================================
|
||||
|
||||
.. warning::
|
||||
It is highly recommended that you complete :doc:`01_fields_and_views` before starting this
|
||||
@@ -30,7 +30,7 @@ addon includes the necessary server files to add a new view.
|
||||
|
||||
.. admonition:: Goal
|
||||
|
||||
.. image:: 04_creating_view_from_scratch/overview.png
|
||||
.. image:: 03_create_gallery_view/overview.png
|
||||
:align: center
|
||||
|
||||
.. spoiler:: Solutions
|
||||
@@ -54,10 +54,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.
|
||||
#. Make sure that you can see your hello world component when switching to the gallery view.
|
||||
|
||||
.. image:: 04_creating_view_from_scratch/view_button.png
|
||||
.. image:: 03_create_gallery_view/view_button.png
|
||||
:align: center
|
||||
|
||||
.. image:: 04_creating_view_from_scratch/new_view.png
|
||||
.. image:: 03_create_gallery_view/new_view.png
|
||||
:align: center
|
||||
|
||||
2. Use the Layout component
|
||||
@@ -72,7 +72,7 @@ have the standard features like other views.
|
||||
#. Update the template to use `Layout`. It needs a `display` prop, which can be found in
|
||||
`props.display`.
|
||||
|
||||
.. image:: 04_creating_view_from_scratch/layout.png
|
||||
.. image:: 03_create_gallery_view/layout.png
|
||||
:align: center
|
||||
|
||||
3. Parse the arch
|
||||
@@ -135,7 +135,7 @@ Let us now get some real data.
|
||||
.. note::
|
||||
The loading data code will be moved into a proper model in the next exercise.
|
||||
|
||||
.. image:: 04_creating_view_from_scratch/gallery_data.png
|
||||
.. image:: 03_create_gallery_view/gallery_data.png
|
||||
:align: center
|
||||
|
||||
5. Reorganize code
|
||||
@@ -158,7 +158,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
|
||||
empty, display an empty box instead.
|
||||
|
||||
.. image:: 04_creating_view_from_scratch/tshirt_images.png
|
||||
.. image:: 03_create_gallery_view/tshirt_images.png
|
||||
:align: center
|
||||
|
||||
7. Switch to form view on click
|
||||
@@ -191,7 +191,7 @@ It is useful to have some additional information on mouse hover.
|
||||
char field, a number field or a many2one field.
|
||||
#. Update the orders gallery view to add the customer as tooltip field.
|
||||
|
||||
.. image:: 04_creating_view_from_scratch/image_tooltip.png
|
||||
.. image:: 03_create_gallery_view/image_tooltip.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
@@ -206,7 +206,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.
|
||||
Note that it is surprisingly difficult.
|
||||
|
||||
.. image:: 04_creating_view_from_scratch/pagination.png
|
||||
.. image:: 03_create_gallery_view/pagination.png
|
||||
:align: center
|
||||
|
||||
.. 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,6 +1,6 @@
|
||||
=============================
|
||||
Chapter 3: Custom kanban view
|
||||
=============================
|
||||
==================================
|
||||
Chapter 4: Customize a kanban view
|
||||
==================================
|
||||
|
||||
.. todo:: It'd be cool to follow the naming convention of the previous chapters: "Chapter N: The concept studied in the chapter"
|
||||
|
||||
@@ -21,7 +21,7 @@ orders linked to that customer.
|
||||
|
||||
.. admonition:: Goal
|
||||
|
||||
.. image:: 03_custom_kanban_view/overview.png
|
||||
.. image:: 04_customize_kanban_view/overview.png
|
||||
:align: center
|
||||
|
||||
.. spoiler:: Solutions
|
||||
@@ -58,7 +58,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.
|
||||
#. Make sure you see your component in the kanban view.
|
||||
|
||||
.. image:: 03_custom_kanban_view/customer_list.png
|
||||
.. image:: 04_customize_kanban_view/customer_list.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
@@ -71,7 +71,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`.
|
||||
#. Whenever a customer is selected, call the `selectCustomer` function prop.
|
||||
|
||||
.. image:: 03_custom_kanban_view/customer_data.png
|
||||
.. image:: 04_customize_kanban_view/customer_data.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
@@ -96,7 +96,7 @@ We will need to display a list of customers, so we might as well create the comp
|
||||
});
|
||||
}
|
||||
|
||||
.. image:: 03_custom_kanban_view/customer_filter.png
|
||||
.. image:: 04_customize_kanban_view/customer_filter.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
@@ -112,7 +112,7 @@ customers with an active order.
|
||||
next to it.
|
||||
#. Changing the value of the checkbox should filter the list on customers with an active order.
|
||||
|
||||
.. image:: 03_custom_kanban_view/active_customer.png
|
||||
.. image:: 04_customize_kanban_view/active_customer.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
@@ -127,7 +127,7 @@ customers with an active order.
|
||||
.. tip::
|
||||
You can use the `fuzzyLookup` function to perform the filter.
|
||||
|
||||
.. image:: 03_custom_kanban_view/customer_search.png
|
||||
.. image:: 04_customize_kanban_view/customer_search.png
|
||||
:align: center
|
||||
:scale: 60%
|
||||
|
||||
@@ -166,6 +166,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
|
||||
previous exercise. There are many edge cases to take into account.
|
||||
|
||||
.. image:: 03_custom_kanban_view/customer_pager.png
|
||||
.. image:: 04_customize_kanban_view/customer_pager.png
|
||||
:align: center
|
||||
: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,80 +0,0 @@
|
||||
==================
|
||||
Chapter 5: Testing
|
||||
==================
|
||||
|
||||
Automatically testing code is important when working on a codebase. It helps ensure we don't
|
||||
introduce (too many) bugs or regressions. Let us see how to test our code.
|
||||
|
||||
.. spoiler:: Solutions
|
||||
|
||||
The solutions for each exercise of the chapter are hosted on the
|
||||
`official Odoo tutorials repository
|
||||
<https://github.com/odoo/tutorials/commits/{CURRENT_MAJOR_BRANCH}-solutions>`_.
|
||||
|
||||
1. Integration testing
|
||||
======================
|
||||
|
||||
To make sure our application works as expected, we can perform :ref:`integration testing
|
||||
<reference/testing/integration-testing>` by creating a tour: this is a sequence of steps that we
|
||||
can execute. Each step wait until some desired DOM state is reached, then performs an action. If, at
|
||||
some point, it is unable to go to the next step for a long time, the tour fails.
|
||||
|
||||
Let's write a tour to ensure that it is possible to perform an tshirt order from our public route
|
||||
|
||||
.. exercise::
|
||||
|
||||
#. In the `awesome_tshirt` addon, add a :file:`/static/tests/tours` folder.
|
||||
#. Add a :file:`/static/tests/tours/order_flow.js` file.
|
||||
#. Add a tour that performs the following steps:
|
||||
|
||||
#. Open the `/awesome_tshirt/order` route.
|
||||
#. Fill the order form.
|
||||
#. Validate it.
|
||||
#. Navigate to our webclient.
|
||||
#. Open the list view for the the t-shirt order.
|
||||
#. Check that our order can be found in the list.
|
||||
|
||||
#. Run the tour manually.
|
||||
#. Add a Python test to run it programmatically.
|
||||
#. Run the tour from the terminal.
|
||||
|
||||
2. Unit testing a Component
|
||||
===========================
|
||||
|
||||
It is also useful to test independently a component or a piece of code. :ref:`QUnit
|
||||
<reference/testing/qunit>` tests are useful to quickly locate an issue.
|
||||
|
||||
.. exercise::
|
||||
|
||||
#. 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.
|
||||
|
||||
.. image:: 05_testing/component_test.png
|
||||
:align: center
|
||||
|
||||
.. seealso::
|
||||
|
||||
`Example: Testing an Owl component
|
||||
<{GITHUB_PATH}/addons/web/static/tests/core/checkbox_tests.js>`_
|
||||
|
||||
3. Unit testing our gallery view
|
||||
================================
|
||||
|
||||
Many components need more setup to be tested. In particular, we often need to mock some demo data.
|
||||
Let us see how to do that.
|
||||
|
||||
.. note::
|
||||
This depends on our Gallery View from :doc:`04_creating_view_from_scratch`.
|
||||
|
||||
.. exercise::
|
||||
|
||||
#. In the `awesome_gallery` addon, add a :file:`/static/tests/gallery_view_tests.js` file.
|
||||
#. Add a test that instantiates the gallery view with some demo data.
|
||||
#. Add another test that checks that when the user clicks on an image, it is switched to the form
|
||||
view of the corresponding order.
|
||||
|
||||
.. image:: 05_testing/view_test.png
|
||||
:align: center
|
||||
|
||||
.. seealso::
|
||||
`Example: Testing a list view <{GITHUB_PATH}/addons/web/static/tests/views/list_view_tests.js>`_
|
||||
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 43 KiB |