[ADD] some documentation on the search view

bzr revid: xmo@openerp.com-20110328194809-yw0oyo6db5iyy1tk
This commit is contained in:
Xavier Morel 2011-03-28 21:48:09 +02:00
parent 7b711fd117
commit f15f180777
2 changed files with 276 additions and 4 deletions

View File

@ -614,9 +614,9 @@ openerp.base.search.Widget = openerp.base.Controller.extend({
/**
* Sets and returns a globally unique identifier for the widget.
*
* If a prefix is appended, the identifier will be appended to it.
* If a prefix is specified, the identifier will be appended to it.
*
* @params sections prefix sections, empty/falsy sections will be removed
* @params prefix prefix sections, empty/falsy sections will be removed
*/
make_id: function () {
this.element_id = _.uniqueId(

View File

@ -1,5 +1,5 @@
Contributing to OpenERP Web
===========================
OpenERP Web Core and standard addons
====================================
* General organization and core ideas (design philosophies)
* Internal documentation, autodoc, Python and JS domains
@ -8,6 +8,278 @@ Contributing to OpenERP Web
* Style guide and coding conventions (PEP8? More)
* Test frameworks in JS?
Standard Views
--------------
Search View
+++++++++++
The OpenERP search view really is a sub-view, used in support of views
acting on collections of records (list view or graph view, for
instance).
Its main goal is to collect information from its widgets (themselves
collecting information from the users) and make those available to the
rest of the client.
The search view's root is :js:class:`~openerp.base.SearchView`. This
object should never need to be created or managed directly, its
lifecycle should be driven by the
:js:class:`~openerp.base.ViewManager`.
.. TODO: insert SearchView constructor here
The search view defines a number of internal and external protocols to
communicate with the objects around and within it. Most of these
protocols are informal, and types available for inheritance are more
mixins than mandatory.
Events
""""""
``on_loaded``
.. TODO: method openerp.base.SearchView.on_loaded
Fires when the search view receives its view data (the result of
``fields_view_get``). Hooking up before the event allows for
altering view data before it can be used.
By the time ``on_loaded`` is done, the search view is guaranteed to
be fully set up and ready to use.
``on_search``
.. TODO: method openerp.base.SearchView.on_search
Event triggered after a user asked for a search. The search view
fires this event after collecting all input data (contexts, domains
and group_by contexts). Note that the search view does *not* merge
those (or therwise evaluate them), they are returned as provided by
the various inputs within the view.
``on_clear``
.. TODO: method openerp.base.SearchView.on_clear
Triggered after a user asked for a form clearing.
Input management
""""""""""""""""
An important concept in the search view is that of input. It is both
an informal protocol and an abstract type that can be inherited from.
Inputs are widgets which can contain user data (a char widget for
instance, or a selection box). They are able of action and of
reaction:
.. _views-search-registration:
``registration``
This is an input action. Inputs have to register themselves to the
main view (which they receive as a constructor argument). This is
performed by pushing themselves on the
:js:attr:`openerp.base.SearchView.inputs` array.
``get_context``
An input reaction. When it needs to collect contexts, the view calls
``get_context()`` on all its inputs.
Inputs can react in the following manners:
* Return a context (an object), this is the "normal" response if the
input holds a value.
* Return a falsy value (generally ``null``). This value indicates
the input does not contain any value and will not take part in the
research.
* Raise :js:class:`openerp.base.search.Invalid` to indicate that it
holds a value but this value can not be used in the search
(because it is incorrectly formatted or nonsensical). Raising
:js:class:`~openerp.base.search.Invalid` is guaranteed to cancel
the search process.
:js:class:`~openerp.base.search.Invalid` takes three mandatory
arguments: an indentifier (a name for instance), the invalid value
and a validation message indicating the issue.
``get_domain``
The second input reaction, the possible behaviors of inputs are the
same as for ``get_context``.
The :js:class:`openerp.base.search.Input` type implements registration
on its own, but its implementations of ``get_context`` and
``get_domain`` simply raise errors and *have* to be overridden.
One last action is for filters, as an activation order has to be kept
on them for some controls (establish the correct grouping sequence for
instance).
To that end, filters can call
:js:func:`openerp.base.Search.do_toggle_filter`, providing themselves
as first argument.
Filters calling :js:func:`~openerp.base.Search.do_toggle_filter` also
need to implement a method called
:js:func:`~openerp.base.search.Filter.is_enabled`, which the search
view will use to know the current status of the filter.
The search view automatically triggers a search after calls to
:js:func:`~openerp.base.Search.do_toggle_filter`.
Life cycle
""""""""""
The search view has a pretty simple and linear life cycle, in three main steps:
:js:class:`init <openerp.base.SearchView>`
Nothing interesting happens here
:js:func:`~openerp.base.SearchView.start`
Called by the main view's creator, this is the main initialization
step for the list view.
It begins with a remote call to fetch the view's descriptors
(``fields_view_get``).
Once the remote call is complete, the ``on_loaded`` even happens,
holding three main operations:
:js:func:`~openerp.base.SearchView.make_widgets`
Builds and returns the top-level widgets of the search
view. Because it returns an array of widget lines (a 2-dimensional
matrix of widgets) it should be called recursively by container
widgets (:js:class:`openerp.base.search.Group` for instance).
:js:func:`~openerp.base.search.Widget.render`
Called by the search view on all top-level widgets. Container
widgets should recursively call this method on their own children
widgets.
Widgets are provided with a mapping of ``{name: value}`` holding
default values for the search view. They can freely pick their
initial values from there, but must pass the mapping to their
children widgets if they have any.
:js:func:`~openerp.base.search.Widget.start`
The last operation of the search view startup is to initialize all
its widgets in order. This is again done recursively (the search
view starts its children, which have to start their own children).
:js:func:`~openerp.base.SearchView.stop`
Used before discarding a search view, allows the search view to
disable its events and pass the message to its own widgets,
gracefully shutting down the whole view.
Widgets
"""""""
In a search view, the widget is simply a unit of display.
All widgets must be able to react to three events, which will be
called in this order:
:js:func:`~openerp.base.search.Widget.render`
Called with a map of default values. The widget must return a
``String``, which is its HTML representation. That string can be
empty (if the widget should not be represented).
Widgets are responsible for asking their children for rendering, and
for passing along the default values.
:js:func:`~openerp.base.search.Widget.start`
Called without arguments. At this point, the widget has been fully
rendered and can set its events up, if any.
The widget is responsible for starting its children, if it has any.
:js:func:`~openerp.base.search.Widget.stop`
Gives the widget the opportunity to unbind its events, remove itself
from the DOM and perform any other cleanup task it may have.
Event if the widget does not do anything itself, it is responsible
for shutting down its children.
An abstract type is available and can be inherited from, to simplify
the implementation of those tasks:
.. TODO: insert Widget here
.. remember to document all methods
Inputs
""""""
The search namespace (``openerp.base.search``) provides two more
abstract types, used to implement input widgets:
* :js:class:`openerp.base.search.Input` is the most basic input type,
it only implements :ref:`input registration
<views-search-registration>`.
If inherited from, descendant classes should not call its
implementations of ``get_context`` and ``get_domain``.
* :js:class:`openerp.base.search.Field` is used to implement more
"field" widgets (which allow the user to input potentially complex
values).
It provides various services for its subclasses:
* Sets up the field attributes, using attributes from the field and
the view node.
* It fills the widget with :js:class:`~openerp.base.search.Filter`
if the field has any child filter.
* It automatically generates an identifier based on the field type
and the field name, using
:js:func:`~openerp.base.search.Widget.make_id`.
* It sets up a basic (overridable)
:js:attr:`~opererp.base.search.Field.template` attribute, combined
with the previous tasks, this makes subclasses of
:js:class:`~openerp.base.search.Field` render themselves "for
free".
* It provides basic implementations of ``get_context`` and
``get_domain``, both hinging on the subclasses implementing
``get_value()`` (which should return a correct, converted
Javascript value):
:js:func:`~openerp.base.search.Field.get_context`
Checks if the field has a non-``null`` and non-empty
(``String``) value, and that the field has a ``context`` attr.
If both conditions are fullfilled, returns the context.
:js:func:`~openerp.base.search.Field.get_domain`
Only requires that the field has a non-``null`` and non-empty
value.
If the field has a ``filter_domain``, returns it
immediately. Otherwise, builds a context using the field's
name, the field :js:attr:`~openerp.base.search.Field.operator`
and the field value, and returns it.
.. TODO: insert Input, Field, Filter, and just about every Field subclass
Internal API Doc
----------------