summaryrefslogtreecommitdiff
path: root/addons/web/static
diff options
context:
space:
mode:
authorJulien Mougenot <jum@odoo.com>2019-06-24 08:14:33 +0000
committerJulien Mougenot <jum@odoo.com>2019-08-16 09:03:49 +0000
commitb416c15a77ce9f2056e2934b91a937cea14210c3 (patch)
tree8ad96fa55282ca5bb0ea3ffc29f1e03adb4e79c6 /addons/web/static
parentbec84c10a1f683f9cc37e76d7fb354ed066508f4 (diff)
[IMP] web: dialog triggers custom callback on close
Added an option in the Dialog class to give it a function to run when it's closed by other ways than by its buttons. Its default value is the "cancel" callback if given, or none. Before this commit, there was no way to add any callback to run when the modal wasn't closed by a button. Now, when exiting the modal by other means (e.g.: "Escape" key), it will run a given callback.
Diffstat (limited to 'addons/web/static')
-rw-r--r--addons/web/static/src/js/core/dialog.js14
-rw-r--r--addons/web/static/tests/core/dialog_tests.js129
2 files changed, 143 insertions, 0 deletions
diff --git a/addons/web/static/src/js/core/dialog.js b/addons/web/static/src/js/core/dialog.js
index 94741f98233..6d02c23664e 100644
--- a/addons/web/static/src/js/core/dialog.js
+++ b/addons/web/static/src/js/core/dialog.js
@@ -60,6 +60,9 @@ var Dialog = Widget.extend({
* Whether or not the dialog should be rendered with header
* @param {boolean} [options.renderFooter=true]
* Whether or not the dialog should be rendered with footer
+ * @param {function} [options.onForceClose]
+ * Callback that triggers when the modal is closed by other means than with the buttons
+ * e.g. pressing ESC
*/
init: function (parent, options) {
var self = this;
@@ -79,6 +82,7 @@ var Dialog = Widget.extend({
backdrop: 'static',
renderHeader: true,
renderFooter: true,
+ onForceClose: false,
});
this.$content = options.$content;
@@ -93,6 +97,7 @@ var Dialog = Widget.extend({
this.backdrop = options.backdrop;
this.renderHeader = options.renderHeader;
this.renderFooter = options.renderFooter;
+ this.onForceClose = options.onForceClose;
core.bus.on('close_dialogs', this, this.destroy.bind(this));
},
@@ -169,6 +174,7 @@ var Dialog = Widget.extend({
def = buttonData.click.call(self, e);
}
if (buttonData.close) {
+ self.onForceClose = false;
Promise.resolve(def).then(self.close.bind(self)).guardedCatch(self.close.bind(self));
}
});
@@ -254,6 +260,11 @@ var Dialog = Widget.extend({
if (this.isDestroyed()) {
return;
}
+
+ // Triggers the onForceClose event if the callback is defined
+ if (this.onForceClose) {
+ this.onForceClose();
+ }
var isFocusSet = this._focusOnClose();
this._super();
@@ -352,6 +363,7 @@ Dialog.alert = function (owner, message, options) {
text: message,
}),
title: _t("Alert"),
+ onForceClose: options && (options.onForceClose || options.confirm_callback),
}, options)).open({shouldFocusButtons:true});
};
@@ -378,6 +390,7 @@ Dialog.confirm = function (owner, message, options) {
text: message,
}),
title: _t("Confirmation"),
+ onForceClose: options && (options.onForceClose || options.cancel_callback),
}, options)).open({shouldFocusButtons:true});
};
@@ -428,6 +441,7 @@ Dialog.safeConfirm = function (owner, message, options) {
buttons: buttons,
$content: $content,
title: _t("Confirmation"),
+ onForceClose: options && (options.onForceClose || options.cancel_callback),
}, options));
dialog.opened(function () {
var $button = dialog.$footer.find('.o_safe_confirm_button');
diff --git a/addons/web/static/tests/core/dialog_tests.js b/addons/web/static/tests/core/dialog_tests.js
new file mode 100644
index 00000000000..ea3a672322f
--- /dev/null
+++ b/addons/web/static/tests/core/dialog_tests.js
@@ -0,0 +1,129 @@
+odoo.define('web.dialog_tests', function (require) {
+"use strict";
+
+var Dialog = require('web.Dialog');
+var testUtils = require('web.test_utils');
+var Widget = require('web.Widget');
+
+var ESCAPE_KEY = $.Event("keyup", { which: 27 });
+
+function createEmptyParent(debug) {
+ var widget = new Widget();
+
+ testUtils.mock.addMockEnvironment(widget, {
+ debug: debug || false,
+ });
+ return widget;
+}
+
+QUnit.module('core', {}, function () {
+
+ QUnit.module('Dialog');
+
+ QUnit.test("Closing custom dialog using buttons calls standard callback", async function (assert) {
+ assert.expect(3);
+
+ var testPromise = testUtils.makeTestPromiseWithAssert(assert, 'custom callback');
+ var parent = createEmptyParent();
+ new Dialog(parent, {
+ buttons: [
+ {
+ text: "Close",
+ classes: 'btn-primary',
+ close: true,
+ click: testPromise.resolve,
+ },
+ ],
+ $content: $('<main/>'),
+ onForceClose: testPromise.reject,
+ }).open();
+
+ assert.verifySteps([]);
+
+ await testUtils.nextTick();
+ await testUtils.dom.click($('.modal[role="dialog"] .btn-primary'));
+
+ testPromise.then(() => {
+ assert.verifySteps(['ok custom callback']);
+ });
+
+ parent.destroy();
+ });
+
+ QUnit.test("Closing custom dialog without using buttons calls force close callback", async function (assert) {
+ assert.expect(3);
+
+ var testPromise = testUtils.makeTestPromiseWithAssert(assert, 'custom callback');
+ var parent = createEmptyParent();
+ new Dialog(parent, {
+ buttons: [
+ {
+ text: "Close",
+ classes: 'btn-primary',
+ close: true,
+ click: testPromise.reject,
+ },
+ ],
+ $content: $('<main/>'),
+ onForceClose: testPromise.resolve,
+ }).open();
+
+ assert.verifySteps([]);
+
+ await testUtils.nextTick();
+ await testUtils.dom.triggerEvents($('.modal[role="dialog"]'), [ESCAPE_KEY]);
+
+ testPromise.then(() => {
+ assert.verifySteps(['ok custom callback']);
+ });
+
+ parent.destroy();
+ });
+
+ QUnit.test("Closing confirm dialog without using buttons calls cancel callback", async function (assert) {
+ assert.expect(3);
+
+ var testPromise = testUtils.makeTestPromiseWithAssert(assert, 'confirm callback');
+ var parent = createEmptyParent();
+ var options = {
+ confirm_callback: testPromise.reject,
+ cancel_callback: testPromise.resolve,
+ };
+ Dialog.confirm(parent, "", options);
+
+ assert.verifySteps([]);
+
+ await testUtils.nextTick();
+ await testUtils.dom.triggerEvents($('.modal[role="dialog"]'), [ESCAPE_KEY]);
+
+ testPromise.then(() => {
+ assert.verifySteps(['ok confirm callback']);
+ });
+
+ parent.destroy();
+ });
+
+ QUnit.test("Closing alert dialog without using buttons calls confirm callback", async function (assert) {
+ assert.expect(3);
+
+ var testPromise = testUtils.makeTestPromiseWithAssert(assert, 'alert callback');
+ var parent = createEmptyParent();
+ var options = {
+ confirm_callback: testPromise.resolve,
+ };
+ Dialog.alert(parent, "", options);
+
+ assert.verifySteps([]);
+
+ await testUtils.nextTick();
+ await testUtils.dom.triggerEvents($('.modal[role="dialog"]'), [ESCAPE_KEY]);
+
+ testPromise.then(() => {
+ assert.verifySteps(['ok alert callback']);
+ });
+
+ parent.destroy();
+ });
+});
+
+});