From 17ef915ff264589710374dd4b966cb0cbfd04730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Tue, 25 Sep 2018 15:52:55 +0200 Subject: [PATCH] [DOC] doc: add information on session and client action --- doc/reference/javascript_cheatsheet.rst | 45 ----- doc/reference/javascript_reference.rst | 211 ++++++++++++++++++++++-- 2 files changed, 193 insertions(+), 63 deletions(-) diff --git a/doc/reference/javascript_cheatsheet.rst b/doc/reference/javascript_cheatsheet.rst index ea22e8f4715..c4d403b6b8e 100644 --- a/doc/reference/javascript_cheatsheet.rst +++ b/doc/reference/javascript_cheatsheet.rst @@ -130,51 +130,6 @@ This is usually done with code looking like this: }); -Adding a client action -====================== - -A client action is a widget which will control the part of the screen below the -menu bar. It can have a control panel, if necessary. Defining a client action -can be done in two steps: implementing a new widget, and registering the widget -in the action registry. - -- Implementing a new client action: - This is done by creating a widget: - - .. code-block:: javascript - - var ControlPanelMixin = require('web.ControlPanelMixin'); - var AbstractAction = require('web.AbstractAction'); - - var ClientAction = AbstractAction.extend(ControlPanelMixin, { - ... - }); - - Do not add the controlpanel mixin if you do not need it. Note that some - code is needed to interact with the control panel (via the - ``update_control_panel`` method given by the mixin). - -- Registering the client action: - As usual, we need to make the web client aware of the mapping between - client actions and the actual class: - - .. code-block:: javascript - - var core = require('web.core'); - - core.action_registry.add('my-custom-action', ClientAction); - - - Then, to use the client action in the web client, we need to create a client - action record (a record of the model ``ir.actions.client``) with the proper - ``tag`` attribute: - - .. code-block:: xml - - - Some Name - my-custom-action - Creating a new view (from scratch) ================================== diff --git a/doc/reference/javascript_reference.rst b/doc/reference/javascript_reference.rst index 8089fd1205e..c8572a6fad7 100644 --- a/doc/reference/javascript_reference.rst +++ b/doc/reference/javascript_reference.rst @@ -616,23 +616,23 @@ Widget API generated DOM root with the following attributes: - .. attribute:: Widget.id +.. attribute:: Widget.id - Used to generate an ``id`` attribute on the generated DOM - root. Note that this is rarely needed, and is probably not a good idea - if a widget can be used more than once. + Used to generate an ``id`` attribute on the generated DOM + root. Note that this is rarely needed, and is probably not a good idea + if a widget can be used more than once. - .. attribute:: Widget.className +.. attribute:: Widget.className - Used to generate a ``class`` attribute on the generated DOM root. Note - that it can actually contain more than one css class: - *'some-class other-class'* + Used to generate a ``class`` attribute on the generated DOM root. Note + that it can actually contain more than one css class: + *'some-class other-class'* - .. attribute:: Widget.attributes +.. attribute:: Widget.attributes - Mapping (object literal) of attribute names to attribute - values. Each of these k:v pairs will be set as a DOM attribute - on the generated DOM root. + Mapping (object literal) of attribute names to attribute + values. Each of these k:v pairs will be set as a DOM attribute + on the generated DOM root. .. attribute:: Widget.el @@ -651,13 +651,21 @@ Widget API initialized but before it has been started. The root element generated by the template will be set as the DOM root of the widget. -.. attribute:: xmlDependencies +.. attribute:: Widget.xmlDependencies List of paths to xml files that need to be loaded before the widget can be rendered. This will not induce loading anything that has already - been loaded. + been loaded. This is useful when you want to load your templates lazily, + or if you want to share a widget between the website and the web client + interface. -.. attribute:: events + .. code-block:: javascript + + var EditorMenuBar = Widget.extend({ + xmlDependencies: ['/web_editor/static/src/xml/editor.xml'], + ... + +.. attribute:: Widget.events Events are a mapping of an event selector (an event name and an optional CSS selector separated by a space) to a callback. The callback can @@ -682,7 +690,7 @@ Widget API Note: the use of an inline function is discouraged, and will probably be removed sometimes in the future. -.. attribute:: custom_events +.. attribute:: Widget.custom_events this is almost the same as the *events* attribute, but the keys are arbitrary strings. They represent business events triggered by @@ -1265,6 +1273,55 @@ when the module is loaded. Note that translation functions need some care. The string given in argument should not be dynamic. +Session +======= + +There is a specific module provided by the web client which contains some +information specific to the user current *session*. Some notable keys are + +- uid: the current user ID (its ID as a *res.users*) +- user_name: the user name, as a string +- the user context (user ID, language and timezone) +- partner_id: the ID of the partner associated to the current user +- db: the name of the database currently being in use + +Adding information to the session +--------------------------------- + +When the /web route is loaded, the server will inject some session information +in the template a script tag. The information will be read from the method +*session_info* of the model *ir.http*. So, if one wants to add a specific +information, it can be done by overriding the session_info method and adding it +to the dictionary. + +.. code-block:: python + + from odoo import models + from odoo.http import request + + + class IrHttp(models.AbstractModel): + _inherit = 'ir.http' + + def session_info(self): + result = super(IrHttp, self).session_info() + result['some_key'] = get_some_value_from_db() + return result + +Now, the value can be obtained in javascript by reading it in the session: + +.. code-block:: javascript + + var session = require('web.session'); + var myValue = session.some_key; + ... + +Note that this mechanism is designed to reduce the amount of communication +needed by the web client to be ready. It is more appropriate for data which is +cheap to compute (a slow session_info call will delay the loading for the web +client for everyone), and for data which is required early in the initialization +process. + Views ====== @@ -1400,6 +1457,7 @@ order. Options: - type: setting the input type (*text* by default, can be set on *number*) + On edit mode, the field is rendered as an input with the HTML attribute type setted on *number* (so user can benefit the native support, especially on mobile). In this case, the default formatting is disabled to avoid incompability. @@ -1409,7 +1467,7 @@ order. - step: set the step to the value up and down when the user click on buttons - (only for input of type number, 1 by default) + (only for input of type number, 1 by default) .. code-block:: xml @@ -1431,6 +1489,7 @@ order. Options: - type: setting the input type (*text* by default, can be set on *number*) + On edit mode, the field is rendered as an input with the HTML attribute type setted on *number* (so user can benefit the native support, especially on mobile). In this case, the default formatting is disabled to avoid incompability. @@ -1440,7 +1499,7 @@ order. - step: set the step to the value up and down when the user click on buttons - (only for input of type number, 1 by default) + (only for input of type number, 1 by default) .. code-block:: xml @@ -1996,6 +2055,122 @@ Relational fields This widget is exactly the same as a FieldOne2Many. It is registered at this key only for backward compatibility reasons. Please avoid using this. + +Client actions +============== + +The idea of a client action is a customized widget that is integrated in the +web client interface, just like a *act_window_action*. This is useful when +you need a component that is not closely linked to an existing view or a +specific model. For example, the Discuss application is actually a client +action. + +A client action is a term that has various meanings, depending on the context: + +- from the perspective of the server, it is a record of the model *ir_action*, + with a field *tag* of type char +- from the perspective of the web client, it is a widget, which inherit from + the class AbstractAction, and is supposed to be registered in the + action registry under the corresponding key (from the field char) + +Whenever a menu item is associated to a client action, opening it will simply +fetch the action definition from the server, then lookup into its action +registry to get the Widget definition at the appropriate key, and finally, it +will instantiate and append the widget to the proper place in the DOM. + +Adding a client action +---------------------- + +A client action is a widget which will control the part of the screen below the +menu bar. It can have a control panel, if necessary. Defining a client action +can be done in two steps: implementing a new widget, and registering the widget +in the action registry. + +- Implementing a new client action: + This is done by creating a widget: + + .. code-block:: javascript + + var ControlPanelMixin = require('web.ControlPanelMixin'); + var AbstractAction = require('web.AbstractAction'); + + var ClientAction = AbstractAction.extend(ControlPanelMixin, { + ... + }); + + Do not add the controlpanel mixin if you do not need it. Note that some + code is needed to interact with the control panel (via the + ``update_control_panel`` method given by the mixin). + +- Registering the client action: + As usual, we need to make the web client aware of the mapping between + client actions and the actual class: + + .. code-block:: javascript + + var core = require('web.core'); + + core.action_registry.add('my-custom-action', ClientAction); + + + Then, to use the client action in the web client, we need to create a client + action record (a record of the model ``ir.actions.client``) with the proper + ``tag`` attribute: + + .. code-block:: xml + + + Some Name + my-custom-action + + + +Using the control panel mixin +----------------------------- + +By default, the AbstractAction class does not include the control panel mixin. +This means that a client action does not display a control panel. In order to +do that, several steps should be done. + +- add ControlPanelMixin in the widget: + + .. code-block:: javascript + + var ControlPanelMixin = require('web.ControlPanelMixin'); + + var MyClientAction = AbstractAction.extend(ControlPanelMixin, { + ... + }); + +- call the method *update_control_panel* whenever we need to update the control + panel. For example: + + .. code-block:: javascript + + var SomeClientAction = Widget.extend(ControlPanelMixin, { + ... + start: function () { + this._renderButtons(); + this._updateControlPanel(); + ... + }, + do_show: function () { + ... + this._updateControlPanel(); + }, + _renderButtons: function () { + this.$buttons = $(QWeb.render('SomeTemplate.Buttons')); + this.$buttons.on('click', ...); + }, + _updateControlPanel: function () { + this.update_control_panel({ + cp_content: { + $buttons: this.$buttons, + }, + }); + +For more information, look into the *control_panel.js* file. + .. _.appendTo(): http://api.jquery.com/appendTo/