From 5122dab978f99566e54b080554d340ed7f8559c0 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 5 Dec 2012 14:28:54 +0100 Subject: [PATCH 1/2] [ADD] bit o' tutorial for web modules bzr revid: xmo@openerp.com-20121205132854-j0r8qgh5u2qwlqj1 --- addons/web/doc/module.rst | 281 ++++++++++++++++++ addons/web/doc/module/__init__.py | 0 addons/web/doc/module/__openerp__.py | 7 + addons/web/doc/module/__openerp__.py.1.diff | 11 + addons/web/doc/module/__openerp__.py.2.diff | 11 + addons/web/doc/module/__openerp__.py.3.diff | 12 + addons/web/doc/module/__openerp__.py.4.diff | 13 + addons/web/doc/module/__openerp__.py.5.diff | 14 + .../doc/module/static/src/css/web_example.css | 6 + .../static/src/css/web_example.css.1.diff | 17 ++ .../doc/module/static/src/js/first_module.js | 2 + .../static/src/js/first_module.js.1.diff | 8 + .../static/src/js/first_module.js.2.diff | 11 + .../static/src/js/first_module.js.3.diff | 18 ++ .../static/src/js/first_module.js.4.diff | 15 + .../static/src/js/first_module.js.5.diff | 23 ++ .../static/src/js/first_module.js.6.diff | 55 ++++ .../doc/module/static/src/xml/web_example.xml | 11 + addons/web/doc/module/web_example.xml | 11 + addons/web/doc/widget.rst | 2 + 20 files changed, 528 insertions(+) create mode 100644 addons/web/doc/module.rst create mode 100644 addons/web/doc/module/__init__.py create mode 100644 addons/web/doc/module/__openerp__.py create mode 100644 addons/web/doc/module/__openerp__.py.1.diff create mode 100644 addons/web/doc/module/__openerp__.py.2.diff create mode 100644 addons/web/doc/module/__openerp__.py.3.diff create mode 100644 addons/web/doc/module/__openerp__.py.4.diff create mode 100644 addons/web/doc/module/__openerp__.py.5.diff create mode 100644 addons/web/doc/module/static/src/css/web_example.css create mode 100644 addons/web/doc/module/static/src/css/web_example.css.1.diff create mode 100644 addons/web/doc/module/static/src/js/first_module.js create mode 100644 addons/web/doc/module/static/src/js/first_module.js.1.diff create mode 100644 addons/web/doc/module/static/src/js/first_module.js.2.diff create mode 100644 addons/web/doc/module/static/src/js/first_module.js.3.diff create mode 100644 addons/web/doc/module/static/src/js/first_module.js.4.diff create mode 100644 addons/web/doc/module/static/src/js/first_module.js.5.diff create mode 100644 addons/web/doc/module/static/src/js/first_module.js.6.diff create mode 100644 addons/web/doc/module/static/src/xml/web_example.xml create mode 100644 addons/web/doc/module/web_example.xml diff --git a/addons/web/doc/module.rst b/addons/web/doc/module.rst new file mode 100644 index 00000000000..1bdb7c14799 --- /dev/null +++ b/addons/web/doc/module.rst @@ -0,0 +1,281 @@ +Building an OpenERP Web module +============================== + +There is no significant distinction between an OpenERP Web module and +an OpenERP module, the web part is mostly additional data and code +inside a regular OpenERP module. This allows providing more seamless +features by integrating your module deeper into the web client. + +A Basic Module +-------------- + +A very basic OpenERP module structure will be our starting point: + +.. code-block:: text + + web_example + ├── __init__.py + └── __openerp__.py + +.. literalinclude:: module/__openerp__.py + :language: python + +This is a sufficient minimal declaration of a valid OpenERP module. + +Web Declaration +--------------- + +There is no such thing as a "web module" declaration. An OpenERP +module is automatically recognized as "web-enabled" if it contains a +``static`` directory at its root, so: + +.. code-block:: text + + web_example + ├── __init__.py + ├── __openerp__.py + └── static + +is the extent of it. You should also change the dependency to list +``web``: + +.. literalinclude:: module/__openerp__.py.1.diff + :language: diff + +.. note:: + + This does not matter in normal operation so you may not realize + it's wrong (the web module does the loading of everything else, so + it can only be loaded), but when e.g. testing the loading process + is slightly different than normal, and incorrect dependency may + lead to broken code. + +This makes the "web" discovery system consider the module as having a +"web part", and check if it has web controllers to mount or javascript +files to load. The content of the ``static/`` folder is also +automatically made available to web browser at the URL +``$module-name/static/$file-path``. This is sufficient to provide +pictures (of cats, usually) through your module. However there are +still a few more steps to running javascript code. + +Getting Things Done +------------------- + +The first one is to add javascript code. It's customary to put it in +``static/src/js``, to have room for e.g. other file types, or +third-party libraries. + +.. literalinclude:: module/static/src/js/first_module.js + :language: javascript + +The client won't load any file unless specified, thus the new file +should be listed in the module's manifest file, under a new key ``js`` +(a list of file names, or glob patterns): + +.. literalinclude:: module/__openerp__.py.2.diff + :language: diff + +At this point, if the module is installed and the client reloaded the +message should appear in your browser's development console. + +.. note:: + + Because the manifest file has been edited, you will have to + restart the OpenERP server itself for it to be taken in account. + + You may also want to open your browser's console *before* + reloading, depending on the browser messages printed while the + console is closed may not work or may not appear after opening it. + +.. note:: + + If the message does not appear, try cleaning your browser's caches + and ensure the file is correctly loaded from the server logs or + the "resources" tab of your browser's developers tools. + +At this point the code runs, but it runs only once when the module is +initialized, and it can't get access to the various APIs of the web +client (such as making RPC requests to the server). This is done by +providing a `javascript module`_: + +.. literalinclude:: module/static/src/js/first_module.js.1.diff + :language: diff + +If you reload the client, you'll see a message in the console exactly +as previously. The differences, though invisible at this point, are: + +* All javascript files specified in the manifest (only this one so + far) have been fully loaded +* An instance of the web client and a namespace inside that instance + (with the same name as the module) have been created and are + available for use + +The latter point is what the ``instance`` parameter to the function +provides: an instance of the OpenERP Web client, with the contents of +all the new module's dependencies loaded in and initialized. These are +the entry points to the web client's APIs. + +To demonstrate, let's build a simple :doc:`client action +`: a stopwatch + +First, the action declaration: + +.. literalinclude:: module/__openerp__.py.3.diff + :language: diff + +.. literalinclude:: module/web_example.xml + :language: xml + +then set up the :doc:`client action hook ` to register +a function (for now): + +.. literalinclude:: module/static/src/js/first_module.js.2.diff + :language: diff + +Updating the module (in order to load the XML description) and +re-starting the server should display a new menu *Example Client +Action* at the top-level. Opening said menu will make the message +appear, as usual, in the browser's console. + +Paint it black +-------------- + +The next step is to take control of the page itself, rather than just +print little messages in the console. This we can do by replacing our +client action function by a :doc:`widget`. Our widget will simply use +its :js:func:`~openerp.web.Widget.start` to add some content to its +DOM: + +.. literalinclude:: module/static/src/js/first_module.js.3.diff + :language: diff + +after reloading the client (to update the javascript file), instead of +printing to the console the menu item clears the whole screen and +displays the specified message in the page. + +Since we've added a class on the widget's :ref:`DOM root +` we can now see how to add a stylesheet to a module: +first create the stylesheet file: + +.. literalinclude:: module/static/src/css/web_example.css + :language: css + +then add a reference to the stylesheet in the module's manifest (which +will require restarting the OpenERP Server to see the changes, as +usual): + +.. literalinclude:: module/__openerp__.py.4.diff + :language: diff + +the text displayed by the menu item should now be huge, and +white-on-black (instead of small and black-on-white). From there on, +the world's your canvas. + +.. note:: + + Prefixing CSS rules with both ``.openerp`` (to ensure the rule + will apply only within the confines of the OpenERP Web client) and + a class at the root of your own hierarchy of widgets is strongly + recommended to avoid "leaking" styles in case the code is running + embedded in an other web page, and does not have the whole screen + to itself. + +So far we haven't built much (any, really) DOM content. It could all +be done in :js:func:`~openerp.web.Widget.start` but that gets unwieldy +and hard to maintain fast. It is also very difficult to extend by +third parties (trying to add or change things in your widgets) unless +broken up into multiple methods which each perform a little bit of the +rendering. + +The first way to handle this method is to delegate the content to +plenty of sub-widgets, which can be individually overridden. An other +method [#DOM-building]_ is to use `a template +`_ to render a widget's +DOM. + +OpenERP Web's template language is :doc:`qweb`. Although any +templating engine can be used (e.g. `mustache +`_ or `_.template +`_) QWeb has important features +which other template engines may not provide, and has special +integration to OpenERP Web widgets. + +Adding a template file is similar to adding a style sheet: + +.. literalinclude:: module/static/src/xml/web_example.xml + :language: xml + +.. literalinclude:: module/__openerp__.py.5.diff + :language: diff + +The template can then easily be hooked in the widget: + +.. literalinclude:: module/static/src/js/first_module.js.4.diff + :language: diff + +And finally the CSS can be altered to style the new (and more complex) +template-generated DOM, rather than the code-generated one: + +.. literalinclude:: module/static/src/css/web_example.css.1.diff + :language: diff + +.. note:: + + The last section of the CSS change is an example of "state + classes": a CSS class (or set of classes) on the root of the + widget, which is toggled when the state of the widget changes and + can perform drastic alterations in rendering (usually + showing/hiding various elements). + + This pattern is both fairly simple (to read and understand) and + efficient (because most of the hard work is pushed to the + browser's CSS engine, which is usually highly optimized, and done + in a single repaint after toggling the class). + +The last step (until the next one) is to add some behavior and make +our stopwatch watch. First hook some events on the buttons to toggle +the widget's state: + +.. literalinclude:: module/static/src/js/first_module.js.5.diff + :language: diff + +This demonstrates the use of the "events hash" and event delegation to +declaratively handle events on the widget's DOM. And already changes +the button displayed in the UI. Then comes some actual logic: + +.. literalinclude:: module/static/src/js/first_module.js.6.diff + :language: diff + +* An initializer (the ``init`` method) is introduced to set-up a few + internal variables: ``_start`` will hold the start of the timer (as + a javascript Date object), and ``_watch`` will hold a ticker to + update the interface regularly and display the "current time". + +* ``update_counter`` is in charge of taking the time difference + between "now" and ``_start``, formatting as ``HH:MM:SS`` and + displaying the result on screen. + +* ``watch_start`` is augmented to initialize ``_start`` with its value + and set-up the update of the counter display every 33ms. + +* ``watch_stop`` disables the updater, does a final update of the + counter display and resets everything. + +* Finally, because javascript Interval and Timeout objects execute + "outside" the widget, they will keep going even after the widget has + been destroyed (especially an issue with intervals as they repeat + indefinitely). So ``_watch`` *must* be cleared when the widget is + destroyed (then the ``_super`` must be called as well in order to + perform the "normal" widget cleanup). + +Starting and stopping the watch now works, and correctly tracks time +since having started the watch, neatly formatted. + +.. [#DOM-building] they are not alternative solutions: they work very + well together. Templates are used to build "just + DOM", sub-widgets are used to build DOM subsections + *and* delegate part of the behavior (e.g. events + handling). + +.. _javascript module: + http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript diff --git a/addons/web/doc/module/__init__.py b/addons/web/doc/module/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/web/doc/module/__openerp__.py b/addons/web/doc/module/__openerp__.py new file mode 100644 index 00000000000..d8c23c34f10 --- /dev/null +++ b/addons/web/doc/module/__openerp__.py @@ -0,0 +1,7 @@ +# __openerp__.py +{ + 'name': "Web Example", + 'description': "Basic example of a (future) web module", + 'category': 'Hidden', + 'depends': ['base'], +} diff --git a/addons/web/doc/module/__openerp__.py.1.diff b/addons/web/doc/module/__openerp__.py.1.diff new file mode 100644 index 00000000000..dbab2e65437 --- /dev/null +++ b/addons/web/doc/module/__openerp__.py.1.diff @@ -0,0 +1,11 @@ +--- web_example/__openerp__.py ++++ web_example/__openerp__.py +@@ -1,7 +1,7 @@ + # __openerp__.py + { + 'name': "Web Example", + 'description': "Basic example of a (future) web module", + 'category': 'Hidden', +- 'depends': ['base'], ++ 'depends': ['web'], + } diff --git a/addons/web/doc/module/__openerp__.py.2.diff b/addons/web/doc/module/__openerp__.py.2.diff new file mode 100644 index 00000000000..77025f11512 --- /dev/null +++ b/addons/web/doc/module/__openerp__.py.2.diff @@ -0,0 +1,11 @@ +--- web_example/__openerp__.py ++++ web_example/__openerp__.py +@@ -1,7 +1,8 @@ + # __openerp__.py + { + 'name': "Web Example", + 'description': "Basic example of a (future) web module", + 'category': 'Hidden', + 'depends': ['web'], ++ 'js': ['static/src/js/first_module.js'], + } diff --git a/addons/web/doc/module/__openerp__.py.3.diff b/addons/web/doc/module/__openerp__.py.3.diff new file mode 100644 index 00000000000..e100098bce9 --- /dev/null +++ b/addons/web/doc/module/__openerp__.py.3.diff @@ -0,0 +1,12 @@ +--- web_example/__openerp__.py ++++ web_example/__openerp__.py +@@ -1,8 +1,9 @@ + # __openerp__.py + { + 'name': "Web Example", + 'description': "Basic example of a (future) web module", + 'category': 'Hidden', + 'depends': ['web'], ++ 'data': ['web_example.xml'], + 'js': ['static/src/js/first_module.js'], + } diff --git a/addons/web/doc/module/__openerp__.py.4.diff b/addons/web/doc/module/__openerp__.py.4.diff new file mode 100644 index 00000000000..78fc90c4b1c --- /dev/null +++ b/addons/web/doc/module/__openerp__.py.4.diff @@ -0,0 +1,13 @@ +--- web_example/__openerp__.py ++++ web_example/__openerp__.py +@@ -1,9 +1,10 @@ + # __openerp__.py + { + 'name': "Web Example", + 'description': "Basic example of a (future) web module", + 'category': 'Hidden', + 'depends': ['web'], + 'data': ['web_example.xml'], + 'js': ['static/src/js/first_module.js'], ++ 'css': ['static/src/css/web_example.css'], + } diff --git a/addons/web/doc/module/__openerp__.py.5.diff b/addons/web/doc/module/__openerp__.py.5.diff new file mode 100644 index 00000000000..c9492420ee8 --- /dev/null +++ b/addons/web/doc/module/__openerp__.py.5.diff @@ -0,0 +1,14 @@ +--- web_example/__openerp__.py ++++ web_example/__openerp__.py +@@ -1,10 +1,11 @@ + # __openerp__.py + { + 'name': "Web Example", + 'description': "Basic example of a (future) web module", + 'category': 'Hidden', + 'depends': ['web'], + 'data': ['web_example.xml'], + 'js': ['static/src/js/first_module.js'], + 'css': ['static/src/css/web_example.css'], ++ 'qweb': ['static/src/xml/web_example.xml'], + } diff --git a/addons/web/doc/module/static/src/css/web_example.css b/addons/web/doc/module/static/src/css/web_example.css new file mode 100644 index 00000000000..b861af8d517 --- /dev/null +++ b/addons/web/doc/module/static/src/css/web_example.css @@ -0,0 +1,6 @@ +.openerp .oe_web_example { + color: white; + background-color: black; + height: 100%; + font-size: 400%; +} diff --git a/addons/web/doc/module/static/src/css/web_example.css.1.diff b/addons/web/doc/module/static/src/css/web_example.css.1.diff new file mode 100644 index 00000000000..442211a252b --- /dev/null +++ b/addons/web/doc/module/static/src/css/web_example.css.1.diff @@ -0,0 +1,17 @@ +--- web_example/static/src/css/web_example.css ++++ web_example/static/src/css/web_example.css +@@ -1,6 +1,13 @@ + .openerp .oe_web_example { + color: white; + background-color: black; + height: 100%; +- font-size: 400%; + } ++.openerp .oe_web_example h4 { ++ margin: 0; ++ font-size: 200%; ++} ++.openerp .oe_web_example.oe_web_example_started .oe_web_example_start button, ++.openerp .oe_web_example.oe_web_example_stopped .oe_web_example_stop button { ++ display: none ++} diff --git a/addons/web/doc/module/static/src/js/first_module.js b/addons/web/doc/module/static/src/js/first_module.js new file mode 100644 index 00000000000..74580d1c0ca --- /dev/null +++ b/addons/web/doc/module/static/src/js/first_module.js @@ -0,0 +1,2 @@ +// static/src/js/first_module.js +console.log("Debug statement: file loaded"); diff --git a/addons/web/doc/module/static/src/js/first_module.js.1.diff b/addons/web/doc/module/static/src/js/first_module.js.1.diff new file mode 100644 index 00000000000..53c153e1971 --- /dev/null +++ b/addons/web/doc/module/static/src/js/first_module.js.1.diff @@ -0,0 +1,8 @@ +--- web_example/static/src/js/first_module.js ++++ web_example/static/src/js/first_module.js +@@ -1,2 +1,4 @@ + // static/src/js/first_module.js +-console.log("Debug statement: file loaded"); ++openerp.web_example = function (instance) { ++ console.log("Module loaded"); ++}; diff --git a/addons/web/doc/module/static/src/js/first_module.js.2.diff b/addons/web/doc/module/static/src/js/first_module.js.2.diff new file mode 100644 index 00000000000..88a80f50fff --- /dev/null +++ b/addons/web/doc/module/static/src/js/first_module.js.2.diff @@ -0,0 +1,11 @@ +--- web_example/static/src/js/first_module.js ++++ web_example/static/src/js/first_module.js +@@ -1,4 +1,7 @@ + // static/src/js/first_module.js + openerp.web_example = function (instance) { +- console.log("Module loaded"); ++ instance.web.client_actions.add('example.action', 'instance.web_example.action'); ++ instance.web_example.action = function (parent, action) { ++ console.log("Executed the action", action); ++ }; + }; diff --git a/addons/web/doc/module/static/src/js/first_module.js.3.diff b/addons/web/doc/module/static/src/js/first_module.js.3.diff new file mode 100644 index 00000000000..295e90b6840 --- /dev/null +++ b/addons/web/doc/module/static/src/js/first_module.js.3.diff @@ -0,0 +1,18 @@ +--- web_example/static/src/js/first_module.js ++++ web_example/static/src/js/first_module.js +@@ -1,7 +1,11 @@ + // static/src/js/first_module.js + openerp.web_example = function (instance) { +- instance.web.client_actions.add('example.action', 'instance.web_example.action'); +- instance.web_example.action = function (parent, action) { +- console.log("Executed the action", action); +- }; ++ instance.web.client_actions.add('example.action', 'instance.web_example.Action'); ++ instance.web_example.Action = instance.web.Widget.extend({ ++ className: 'oe_web_example', ++ start: function () { ++ this.$el.text("Hello, world!"); ++ return this._super(); ++ } ++ }); + }; diff --git a/addons/web/doc/module/static/src/js/first_module.js.4.diff b/addons/web/doc/module/static/src/js/first_module.js.4.diff new file mode 100644 index 00000000000..78a192147e6 --- /dev/null +++ b/addons/web/doc/module/static/src/js/first_module.js.4.diff @@ -0,0 +1,15 @@ +--- web_example/static/src/js/first_module.js ++++ web_example/static/src/js/first_module.js +@@ -1,11 +1,7 @@ + // static/src/js/first_module.js + openerp.web_example = function (instance) { + instance.web.client_actions.add('example.action', 'instance.web_example.Action'); + instance.web_example.Action = instance.web.Widget.extend({ ++ template: 'web_example.action' +- className: 'oe_web_example', +- start: function () { +- this.$el.text("Hello, world!"); +- return this._super(); +- } + }); + }; diff --git a/addons/web/doc/module/static/src/js/first_module.js.5.diff b/addons/web/doc/module/static/src/js/first_module.js.5.diff new file mode 100644 index 00000000000..f345ea319ef --- /dev/null +++ b/addons/web/doc/module/static/src/js/first_module.js.5.diff @@ -0,0 +1,23 @@ +--- web_example/static/src/js/first_module.js ++++ web_example/static/src/js/first_module.js +@@ -1,7 +1,19 @@ + // static/src/js/first_module.js + openerp.web_example = function (instance) { + instance.web.client_actions.add('example.action', 'instance.web_example.Action'); + instance.web_example.Action = instance.web.Widget.extend({ +- template: 'web_example.action' ++ template: 'web_example.action', ++ events: { ++ 'click .oe_web_example_start button': 'watch_start', ++ 'click .oe_web_example_stop button': 'watch_stop' ++ }, ++ watch_start: function () { ++ this.$el.addClass('oe_web_example_started') ++ .removeClass('oe_web_example_stopped'); ++ }, ++ watch_stop: function () { ++ this.$el.removeClass('oe_web_example_started') ++ .addClass('oe_web_example_stopped'); ++ }, + }); + }; diff --git a/addons/web/doc/module/static/src/js/first_module.js.6.diff b/addons/web/doc/module/static/src/js/first_module.js.6.diff new file mode 100644 index 00000000000..7dd17af0e18 --- /dev/null +++ b/addons/web/doc/module/static/src/js/first_module.js.6.diff @@ -0,0 +1,55 @@ +--- web_example/static/src/js/first_module.js ++++ web_example/static/src/js/first_module.js +@@ -1,19 +1,52 @@ + // static/src/js/first_module.js + openerp.web_example = function (instance) { + instance.web.client_actions.add('example.action', 'instance.web_example.Action'); + instance.web_example.Action = instance.web.Widget.extend({ + template: 'web_example.action', + events: { + 'click .oe_web_example_start button': 'watch_start', + 'click .oe_web_example_stop button': 'watch_stop' + }, ++ init: function () { ++ this._super.apply(this, arguments); ++ this._start = null; ++ this._watch = null; ++ }, ++ update_counter: function () { ++ var h, m, s; ++ // Subtracting javascript dates returns the difference in milliseconds ++ var diff = new Date() - this._start; ++ s = diff / 1000; ++ m = Math.floor(s / 60); ++ s -= 60*m; ++ h = Math.floor(m / 60); ++ m -= 60*h; ++ this.$('.oe_web_example_timer').text( ++ _.str.sprintf("%02d:%02d:%02d", h, m, s)); ++ }, + watch_start: function () { + this.$el.addClass('oe_web_example_started') + .removeClass('oe_web_example_stopped'); ++ this._start = new Date(); ++ // Update the UI to the current time ++ this.update_counter(); ++ // Update the counter at 30 FPS (33ms/frame) ++ this._watch = setInterval( ++ this.proxy('update_counter'), ++ 33); + }, + watch_stop: function () { ++ clearInterval(this._watch); ++ this.update_counter(); ++ this._start = this._watch = null; + this.$el.removeClass('oe_web_example_started') + .addClass('oe_web_example_stopped'); + }, ++ destroy: function () { ++ if (this._watch) { ++ clearInterval(this._watch); ++ } ++ this._super(); ++ } + }); + }; diff --git a/addons/web/doc/module/static/src/xml/web_example.xml b/addons/web/doc/module/static/src/xml/web_example.xml new file mode 100644 index 00000000000..b5a9918f2f0 --- /dev/null +++ b/addons/web/doc/module/static/src/xml/web_example.xml @@ -0,0 +1,11 @@ + +
+

00:00:00

+

+ +

+

+ +

+
+
diff --git a/addons/web/doc/module/web_example.xml b/addons/web/doc/module/web_example.xml new file mode 100644 index 00000000000..dfcc1614df4 --- /dev/null +++ b/addons/web/doc/module/web_example.xml @@ -0,0 +1,11 @@ + + + + + Example Client Action + example.action + + + + diff --git a/addons/web/doc/widget.rst b/addons/web/doc/widget.rst index 7466ebaf3e8..1ebc0848e88 100644 --- a/addons/web/doc/widget.rst +++ b/addons/web/doc/widget.rst @@ -33,6 +33,8 @@ view. It provides a number of services to handle a section of a page: * Backbone-compatible shortcuts +.. _widget-dom_root: + DOM Root -------- From 11b3bbce1ce9f8c970c590442aca4f3f8de0689c Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Thu, 6 Dec 2012 10:36:03 +0100 Subject: [PATCH 2/2] [FIX] auth_signup: automatically invite new users to set their password *only* when created from the users form view bzr revid: rco@openerp.com-20121206093603-5zru6o160v20553h --- addons/auth_signup/res_users.py | 2 +- addons/auth_signup/res_users_view.xml | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/addons/auth_signup/res_users.py b/addons/auth_signup/res_users.py index 8380cd8b23f..5fd7917f444 100644 --- a/addons/auth_signup/res_users.py +++ b/addons/auth_signup/res_users.py @@ -254,6 +254,6 @@ class res_users(osv.Model): # overridden to automatically invite user to sign up user_id = super(res_users, self).create(cr, uid, values, context=context) user = self.browse(cr, uid, user_id, context=context) - if user.email: + if context and context.get('reset_password') and user.email: user.action_reset_password() return user_id diff --git a/addons/auth_signup/res_users_view.xml b/addons/auth_signup/res_users_view.xml index 90729c54285..f7bfdd8eeb5 100644 --- a/addons/auth_signup/res_users_view.xml +++ b/addons/auth_signup/res_users_view.xml @@ -2,6 +2,11 @@ + + + {'reset_password': True} + + user.form.state res.users