diff options
| author | Xavier Morel <xmo@odoo.com> | 2018-10-31 16:21:18 +0000 |
|---|---|---|
| committer | Xavier Morel <xmo@odoo.com> | 2019-01-29 10:22:17 +0000 |
| commit | 9db74611ded3dcb64fc57724c032b44d9d170fae (patch) | |
| tree | e63a92c2fe4a170688b0adaaf4d8b8d86316fc35 /addons/web/static | |
| parent | 42fbee83ad2f3f33188cf27a1449b8875c2d8a2a (diff) | |
[IMP] web: action links from bits & pieces
Before this, the action manager only supported auto-triggering actions
from (model, method) or (action_name).
This adds support for providing all the action details via data
attributes:
* model (defaults to current action's)
* resid (defaults to none)
* views (defaults to list, form, unless resid is specified then
defaults to just form)
* domain (defaults to [])
* context (defaults to {active_id, active_ids, active_model} from
current action if the model has not changed, empty otherwise)
The action's name/title is either the link's title (?) or its textual
content.
Diffstat (limited to 'addons/web/static')
| -rw-r--r-- | addons/web/static/src/js/views/abstract_controller.js | 44 | ||||
| -rw-r--r-- | addons/web/static/tests/views/abstract_controller_tests.js | 21 |
2 files changed, 47 insertions, 18 deletions
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js index 77584a272d6..eb773d91057 100644 --- a/addons/web/static/src/js/views/abstract_controller.js +++ b/addons/web/static/src/js/views/abstract_controller.js @@ -421,38 +421,54 @@ var AbstractController = mvc.Controller.extend(ActionMixin, { * When a user clicks on an <a> link with type="action", we need to actually * do the action. This kind of links is used a lot in no-content helpers. * - * The <a> may have - * - a data-method and data-model attribute, in that case the corresponding - * rpc will be called. If that rpc returns an action it will be executed. - * - a data-reload-on-close attribute, in that case the view will be - * reloaded after the dialog has been closed. + * * if the link has both data-model and data-method attributes, the + * corresponding method is called, chained to any action it would + * return. An optional data-reload-on-close (set to a non-falsy value) + * also causes th underlying view to be reloaded after the dialog is + * closed. + * * if the link has a name attribute, invoke the action with that + * identifier (see :class:`ActionManager.doAction` to not get the + * details) + * * otherwise an *action descriptor* is built from the link's data- + * attributes (model, res-id, views, domain and context) * * @private - * @param {OdooEvent} ev + * @param ev */ - _onActionClicked: function (ev) { + _onActionClicked: function (ev) { // FIXME: maybe this should also work on <button> tags? var $target = $(ev.currentTarget); var self = this; - var model = $target.data('model'); - var method = $target.data('method'); + var data = $target.data(); - if (method !== undefined && model !== undefined) { + if (data.method !== undefined && data.model !== undefined) { var options = {}; - if ($target.data('reload-on-close')) { + if (data.reloadOnClose) { options.on_close = function () { self.trigger_up('reload'); }; } this.dp.add(this._rpc({ - model: model, - method: method, + model: data.model, + method: data.method, })).then(function (action) { if (action !== undefined) { self.do_action(action, options); } }); - } else { + } else if ($target.attr('name')) { this.do_action($target.attr('name')); + } else { + this.do_action({ + name: $target.attr('title') || _.str.strip($target.text()), + type: 'ir.actions.act_window', + res_model: data.model || this.modelName, + res_id: data.resId, + target: 'current', // TODO: make customisable? + views: data.views || (data.resId ? [[false, 'form']] : [[false, 'list'], [false, 'form']]), + domain: data.domain || [], + }, { + additional_context: _.extend({}, data.context) + }); } }, /** diff --git a/addons/web/static/tests/views/abstract_controller_tests.js b/addons/web/static/tests/views/abstract_controller_tests.js index cf5810219c7..73bc41d650b 100644 --- a/addons/web/static/tests/views/abstract_controller_tests.js +++ b/addons/web/static/tests/views/abstract_controller_tests.js @@ -43,7 +43,7 @@ odoo.define("base.abstract_controller_tests", function(require) { QUnit.test( 'click on a a[type="action"] child triggers the correct action', function(assert) { - assert.expect(3); + assert.expect(7); var html = "<div>" + @@ -51,6 +51,9 @@ odoo.define("base.abstract_controller_tests", function(require) { '<a name="a2" type="action" class="with-child">' + "<span>child</input>" + "</a>" + + '<a type="action" data-model="foo" data-method="bar" class="method">method</a>' + + '<a type="action" data-model="foo" data-res-id="42" class="descr">descr</a>' + + '<a type="action" data-model="foo" class="descr2">descr2</a>' + "</div>"; var view = createView({ @@ -59,14 +62,24 @@ odoo.define("base.abstract_controller_tests", function(require) { model: "test_model", arch: "<test/>", intercepts: { - do_action: function(event) { - assert.step(event.data.action); + do_action: function (event) { + assert.step(event.data.action.name || event.data.action); } + }, + mockRPC: function (route, args) { + if (args.model === 'foo' && args.method === 'bar') { + assert.step("method"); + return $.when({name: 'method'}); + } + return this._super.apply(this, arguments); } }); testUtils.dom.click(view.$(".simple")); testUtils.dom.click(view.$(".with-child span")); - assert.verifySteps(["a1", "a2"]); + testUtils.dom.click(view.$(".method")); + testUtils.dom.click(view.$(".descr")); + testUtils.dom.click(view.$(".descr2")); + assert.verifySteps(["a1", "a2", "method", "method", "descr", "descr2"]); } ); } |
