summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
authorXavier Morel <xmo@odoo.com>2018-10-31 16:21:18 +0000
committerXavier Morel <xmo@odoo.com>2019-01-29 10:22:17 +0000
commit9db74611ded3dcb64fc57724c032b44d9d170fae (patch)
treee63a92c2fe4a170688b0adaaf4d8b8d86316fc35 /addons
parent42fbee83ad2f3f33188cf27a1449b8875c2d8a2a (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')
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js44
-rw-r--r--addons/web/static/tests/views/abstract_controller_tests.js21
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"]);
}
);
}